jvm打破砂锅问到底- JVM中对象进入老年代的条件

深入理解Java虚拟机书中有详尽描述, 本文做一下咀嚼.
3.8.1 对象优先在Eden分配
3.8.2 大对象直接进入老年代 (默认是关闭的)
-XX:PretenureSizeThreshold:晋升老年代对象大小,超过指定大小直接在老年代分配,默认为0
原因:

  1. 大对象会过度挤压可用内存, 导致提前触发垃圾回收. 所以大对象没有挤占新生代, 如果是没有专门的大对象区的话, 就只能放在老年代了
  2. 新生代是标记复制算法, 大对象需要更高的复制成本.
    这里的大指的是占用内存, 而不是序列化后的大小. 所以一般要复现这个情况得建立数组比如new byte[4 * _1MB]. (成员变量如果是引用类型才占8字节, 如果小于32G指针压缩为4字节, 根据大对象默认是1m判定, 得250个成员变量引用类型, 一般那有这么多, 除非成员变量有数组, 比如有些大数量的arraylist场景, 比方说解析excel或者或者批处理, 处理文件等) 如果设置了PretenureSizeThreshold 所以使用者确定这个大对象应该是需要打老年代的, 就可以直接大对象, 如果使用者认为是朝生夕死的, 就不要触碰到这个大对象的阈值
    3.8.3 长期存活的对象将进入老年代
    老的量化定义, 超过15岁
    3.8.4 动态对象年龄判定
    gc后期, 如果遇到年龄1+年龄2+年龄n的多个年龄对象总和超过了Survivor区域的50%,此时就会把年龄n(含)以上的对象都放入老年代。源自jDK1.8源码逻辑
    提前进入, 意味着留出更多可用空间, 延缓ygc触发垃圾回收.
    原因:个人理解是为了减少空转, 也就是这种情况下更多的可能性是意味着, 这些大龄对象不会突然死亡. 因为占比已经到了50%, 空转的可能性更大. 比如上文说3.8.2的时候, 如果有复杂引用关系, 那就有一堆的小对象, 大家是紧紧相随的, 如果出现空转, 就是类似于一个大对象在空转.
    3.8.5 空间分配担保
    gc后期把Survivor无法容纳的对象直接送入老年代,这与生活中贷款担保类似。老年代要进行这样的担保, JDK 6 Update 24之
    后的规则变为只要老年代的连续空间大于新生代对象总大小或者历次晋升的平均大小,就会进行
    Minor GC,否则将进行Full GC。

你可能感兴趣的:(jvm)