凯哥Java|JVM笔记六-堆区知识之对象生命周期和GC的关系

通过上一篇文章的学习 , 我们对JVM堆区有了初步的认识 , 接下来 , 我们继续展开讲解堆区 。
对象生命周期和GC的关系 。
我们已经知道了 , 堆区的新生区分成了三个部分:伊甸园区、幸存者0区、幸存者1区 。
其中0区也叫from,1区也叫to区 。 但是这个from和to是固定不变的吗?NO,NO,NO不是的 。 当新生区执行一次GC(YGC)后 , from和to区会进行交换 。 交换后 , 也就是在GC之后 , 谁空谁是to区 。 所以 , from区和to区的位置和名分不是一成不变的 。 会发生变化的 。
Java堆从GC的角度可以分为:新生区和老年代 。 这个是从物理分的 。
凯哥Java|JVM笔记六-堆区知识之对象生命周期和GC的关系
文章图片
编辑
新生代和老年代 , 占用堆区的比例是:1比2
在新生代中的伊甸园区和幸存者0区、幸存者1区的占比是:8比1比1
从逻辑来分的话 , 又有永久代(元空间) 。 如下图:
凯哥Java|JVM笔记六-堆区知识之对象生命周期和GC的关系
文章图片
编辑
新生区GC(MinorGC)的过程:复制->清空->互换
1:复制
eden、SurvivorFrom区复制到SurvivorTo区 , 年龄+1
首先 , 当Eden区满的时候会触发第一次GC , 把还存活的对象拷贝到survivorFrom区 , 当Eden区再次触发GC的时候 , 会扫描Eden区和From区域 , 对这两个区域进行垃圾回收 , 经过这次垃圾回收后还存活的对象 , 则直接复制到To区(如果有对象的年龄已经达到了去往老年代的标准 , 则这些达到标准的对象将会被复制到老年代区) , 同时把这些对象的年龄+1
2:清空
清空Eden、survivorFrom区
然后 , 清空Eden和SuriviorFrom中的对象 , 也即是复制之后有交换 。 谁空谁做to区 。
【凯哥Java|JVM笔记六-堆区知识之对象生命周期和GC的关系】3:SurvivorTo和SurvivorFrom互换
最后 , SurvivorTo和SurvivorFrom互换 , 原来SurvivorTo成为下一次GC的SurvivorFrom区 , 部分对象会在From和To区中复制来复制去的 , 如此交换15次(由JVM参赛MaxTenuringThreshold决定的 , 这个参赛默认值就是15) , 最终如果还是存活的对象 , 就把这些存活的对象存入到老年代区域 。
这个过程可以有个生活中的case.士兵到将军的过程 。 士兵上战场 , 幸存下来 , 成班长 , 下次战争来临的时候 , 班长带着新的士兵继续冲杀 , 幸存下来 , 班长升级成排长 , 以此类推 。 经历大大小小战役十五次之后 , 升级成了将军 , 进入到年老代 。
Java7的永久代:
JVM内存管理的模型图如下:
凯哥Java|JVM笔记六-堆区知识之对象生命周期和GC的关系
文章图片
编辑
Why?
真相:经过研究 , 不同对象的生命周期是不同的(废话嘛 , 不同对象 , 操作链路长短不一样 , 当然生命周期不一样了) , 98%的对象是临时对象(临时对象 , 就是用完就被回收了) 。
实际而言 , 方法区(MethodArea)和堆区一样 , 是各个线程共享的内存区域 , 它用于存储虚拟机加载的:类信息+普通常量+静态常量+编译器编译后的代码等等 。 虽然JVM规范将方法区描述为堆的一个逻辑部分 , 但是它却还有一个别名:N0n-Heap(非堆) , 目的就是要和堆区分开的(这句话怎么理解?我们从小教育都知道 , 台湾是中国的一部分 , 但是台湾还有个别名:中华台北 。 其目的就是台湾想在国际上和中国区分开而已) 。
对于HotSpot虚拟机 , 很多开发者习惯将方法区称之为”永久代(ParmanentGen)” , 但严格本质上说两者不同 。 或者说使用永久代来实现方法区而已 , 永久代是方法区(相当于是一个接口Interface)的一个实现 。 JDK1.7的版本中 , 已经将原本存放永久代的字符串常量池移走了 。


推荐阅读