JVM
基本概念
JVM(JAVA virtual Machine)是可以运行Java代码的假想计算机,他是运行在操作系统上的。每一种平台的解释器不同,但是实现的虚拟机是相同的,这也就是Java为什么能够跨平台的原因了。
线程
JVM允许一个应用并发执行多个线程。当线程本地储存,缓冲区分配,栈,程序计数器准备好后,就会创建一个操作系统原生线程。Java线程结束,原生线程随之被回收, 同时释放所有相关资源。
JVM 内存区域
线程私有
生命周期与线程相同,用户线程启动/结束,而创建/销毁
程序计数器 Program Counter Register
- 一块较小的内存空间,每个线程都有一个独立的程序计数器,在这里记录的是虚拟机字节码指令的地址(即当前指令的地址)
虚拟机栈 VM Stack
- 每个方法在执行时都会创建一个栈帧(Stack Frame)用于储存局部变量表,操作数栈,动态链接,方法出口等信息。每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程
- 栈帧随着方法调用而创建,随着方法结束而销毁,无论方法时正常完成还是异常完成都算作方法结束
本地方法栈 Native Method Stack
- 和虚拟机栈类似,区别为虚拟机栈为Java方法服务,而本地方法栈为Native方法服务
线程共享
线程共享区随虚拟机的启动/关闭,而创建/销毁
堆 Heap
- 保存所有创建的对象,数组
- 垃圾收集器进行的最重要内存区域
方法区/永久代 Method Area
- 保存所有被JVM加载的类信息,常量,静态变量,即时编译器编译后的代码等数据
- 运行时常量池 Runtime Constant Pool也是方法区的一部分,用于存放编译期生成的各种字面量和符号引用
JVM 运行时内存
新生代
新生代一般用来存放新生的对象,占据堆1/3的空间,会频繁触发MinorGC。
MinorGC采用复制算法,首先把eden,survivorFrom的存活对象复制到survivorTo区,再把他们的年龄+1。接下来清空eden,survivorFrom中的对象,并把survivorTo 和 survivorFrom互换,原survivorTo内的对象会成为下一次GC的survivorFrom区。
Eden
- Java新对象的出生地,当这个区域内存不够时就会触发MinorGC
SurvivorFrom
- 上一次GC的幸存者,这一次GC的被扫描者
SurvivorTo
- 保留了一次MinorGC过程中的幸存者
老年代
老年代对象稳定,一般在执行MajorGC前都会进行一次MinorGC。 MajorGC采用标记清除算法,扫面所有对象,标记存活对象后回收所有没有标记的对象。
永久代
GC不会在主程序运行期间对永久区进行清理,所以可能出现随着加载class的增多而抛出OOM异常的状况
元数据
JAVA8中,永久代已经移除,被元数据区取代。他并不在虚拟机中,而是使用本地内存。这样,元数据区的大小仅受本地内存限制