JVM内存总共分为5个部分,下面我们就从这5个部分分别进行介绍:
1、程序计数器
最小的一块内存区域,它是线程独享的,指向当前线程执行的字节码;字节码解释器工作时,通过改变程序计数器的值来取出下一条需要执行的命令。
2、堆(下一篇写写垃圾回收器)
是最大的一块内存区域,它是所有线程共享的;几乎所有的对象实例都存放在该区域。
我们平时在java中经常提及的jvm垃圾回收,主要涉及的就是这块的内存;因此我们“堆”也被称为“GC堆”。
根据垃圾回收的原则:我们又把堆分为老年代和年轻代,将年轻代进一步的划分为eden区域、from survive和to survive区域;
堆大小 = 老年代+年轻代
2.1 年轻代
程序创建对象都是从年轻代开始的;jvm只会拿出eden和一块survive区域出来给对象分配地址,也就是说总有一块survive区域是空着的。
2.1.1 未进行GC时,对象分布在eden和from survive区域中,to survive区域是空的;
2.1.2 紧接着发生GC,Eden区域中的对象都会被复制到to survive区域中,而form survive区域中的对象会根据对象年龄来决定去向;
2.1.3 -XX:MaxTenringThreshold设置一个值,大于这个值的对象移动到老年代中,小于这个值的对象移动到to survive区域中;经过这次GC之后,Eden区域和form survive区域会空出来;
2.1.4 此时to survive和from survive完成了角色更替;
上面描述的就是一次minor GC的过程;如果to survive也被填满了,那就将to survive中所有的对象移动到老年代中;
移动就是复制,因为年轻代使用的复制算法
2.2 老年代
用于存放经过多次minor GC依然活着的对象(老兵不死,只是凋零),对象不死,只是进入了老年代中;
老年代中的垃圾回收为FUll GC。
Full GC采用的是标记-清除算法。不同的垃圾回收器使用的算法不尽相同。
3、方法区
方法区也被称为永久代,用于存放虚拟机加载的类信息、静态变量、运行时常量池,是各个线程共享的区域。
运行时常量池是方法区的一部分,用于存放编译器产生的各种符号引用。
4、虚拟机栈
和程序计数器一样,也是线程私有的,它的生命周期与线程相同。每一个方法被调用直至执行结束的过程,都对应着一个栈帧在虚拟中从入栈到出栈的过程。
5、本地方法栈
与虚拟机栈基本类似,也是私有的,区别在于虚拟机栈为虚拟机执行java程序服务,而本地方法栈为虚拟机使用到的native方法服务。