JVM分代模型

重新回过头来看一些 JVM,思考一个问题:分出一个永久代我可以理解,为什么又要把堆分成新生代和老年代呢?私以为划分成新生代和老年代是因为它们里面对象的性质不同,要用不同的垃圾回收算法来回收效率才高,是为垃圾回收器服务才分出新生代和老年代的。

本文说明新生代、老年代和永久代中对象的特性,以及何时它们何时触发 GC。

JVM分代模型

1
2
3
4
5
堆的大小可以用这几个参数来设置:

1. “-XX:InitialHeapSize”和“-XX:MaxHeapSize” 就是初始堆大小和最大堆大小
2. “-XX:NewSize”和“-XX:MaxNewSize” 是初始新生代大小和最大新生代大小
3. “-XX:PretenureSizeThreshold=10485760” 指定了大对象阈值是10MB。

新生代

大部分对象存活的周期很短,就会放在新生代中。ParNew垃圾收集器会使用复制算法,回收新生代中的对象。复制算法中会将新生代分成 Eden 区和两个 Survivor 区,当 Eden 区满的时候就会触发垃圾回收算法。

老年代

少部分对象存活周期比较长,或者因为一些特殊原因会进入到老年代。那么什么样的情况下,对象会进入老年代呢?

  1. 一个实例对象在新生代中,成功躲过 15 次垃圾,就说明他已经15岁了。成为老人的它就能进入到老年代了。

    具体几岁算是一个老人可以通过 -XX:MaxTenuringThreshold 参数进行设置。

  2. 动态年龄判断,当前放对象的 Survivor 区域里,一批对象的总大小大于了这块 Survivor区域内存大小的50%,那么此时大于等于这批对象年龄的对象,就可以直接进入老年代。

  3. 大对象直接进入老年代,可以通过 -XX:PretenureSizeThreshold 参数进行设置

  4. Minor GC 之后发现剩余对象太多,无法放到另一个 Survivor 区,这些对象会直接进入老年代

老年代什么时候会触发 Old GC 呢?其实总结起来有 2 种情况:

  1. 老年代未开启分配担保,老年代对象大小小于新生代中对象大小;老年代开启分配担保,但是老年代对象大小小于历次 Minor GC 之后进入老年代对象的大小。以上情况会进行 Old GC。
  2. 经过 Minor GC 之前的检查,正式进行 Minor GC 后,Survivor 放不下剩余对象,老年代也放不下剩余对象,就会进行 Old GC。

如果 Old GC 之后老年代还是放不下剩余对象,就会 OOM。

具体关于老年代未开启分配机制,以及触发 Minor GC 和 Old GC 流程的内容,可以看《图解GC的过程

永久代

JVM 里的永久代其实就是方法区,可以认为永久代就是放一些类信息的。

永久代一般不会发生 GC,具体情况还不是很清楚,以后会补充。

发布了190 篇原创文章 · 获赞 17 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/shuiCSDN/article/details/104001077