对象进入老年代的动态年龄判断规则(动态晋升年龄计算阈值):Minor GC 时,Survivor 中年龄 1 到 N 的对象大小超过 Survivor 的 50% 时,则将大于等于年龄 N 的对象放入老年代。
《深入理解 Java 虚拟机》书中对动态年龄判断规则的解释大致是:同龄对象大小超过 50% 时,则将大于等于该年龄的对象放入老年代。
以前看到这块的时候一直觉得有点不太理解,因为如果是同龄对象的话,那么这批放入老年代的对象就必然是 1 岁,因为如果在 1 岁的时候没有达到 50%,那么在之后就更不可能达到 50% 了。但也没太在意,直到最近又开始学习 JVM 相关知识,才发现了不一样的解释,囧。
验证:public class TestTargetSurvivorRatio {
private static final int MB = 1024 * 1024;
public static void main(String[] args) throws InterruptedException {
byte[] b1 = new byte[MB * 33];
byte[] b2 = new byte[MB * 33];
byte[] a1 = new byte[MB * 3];
b1 = null;
b2 = null;
System.out.println("--------1 start");
b1 = new byte[MB * 33];
// 垃圾回收完成后:
// 大概1M的系统垃圾+3M的a1进入Survivor,垃圾回收完成后,这些对象就是年龄1
System.out.println("--------1 end");
b2 = new byte[MB * 33];
byte[] a2 = new byte[MB * 3];
b1 = null;
b2 = null;
System.out.println("--------2 start");
// 垃圾回收前,Survivor中的对象年龄1到N的大小不足50%
// 因此在回收的时候年龄1的对象不会进入老年代
b1 = new byte[MB * 33];
// 垃圾回收完成后:
// Survivor中原有的大概1M的系统垃圾+3M的a1变成年龄2
// 新进入Survivor的3M的a2就是年龄1
System.out.println("--------2 end");
b2 = new byte[MB * 33];
byte[] a3 = new byte[MB * 3];
b1 = null;
b2 = null;
System.out.println("--------3 start");
// 垃圾回收前,年龄2有大概4M,年龄1大概有3M,超过Survivor的50%
// 因此在回收的时候年龄2的4M会进入老年代
b1 = new byte[MB * 33];
// 垃圾回收完成后:
// Survivor中3M的a2年龄变成2
// 新进入的3M的a3为年龄1
// 老年代中的则是原先的系统大概1M和3M的a1
System.out.println("--------3 end");
}
}
设置以下 JVM 参数,运行上述代码
-Xmx200M
-Xms200M
-Xmn100M
-XX:SurvivorRatio=8
-XX:MaxTenuringThreshold=15
-XX:PretenureSizeThreshold=100M
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
最终运行结果:( jdk 8)
--------1 start
0.192: [GC (Allocation Failure) 0.192: [ParNew: 77214K->4000K(92160K), 0.0028037 secs] 77214K->4000K(194560K), 0.0029006 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
--------1 end
--------2 start
0.208: [GC (Allocation Failure) 0.208: [ParNew: 76242K->7255K(92160K), 0.0044250 secs] 76242K->7255K(194560K), 0.0044863 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
--------2 end
--------3 start
0.225: [GC (Allocation Failure) 0.225: [ParNew: 81144K->6339K(92160K), 0.0044202 secs] 81144K->10187K(194560K), 0.0044672 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
--------3 end
Heap
par new generation total 92160K, used 42536K [0x00000000f3800000, 0x00000000f9c00000, 0x00000000f9c00000)
eden space 81920K, 44% used [0x00000000f3800000, 0x00000000f5b59160, 0x00000000f8800000)
from space 10240K, 61% used [0x00000000f9200000, 0x00000000f9830f80, 0x00000000f9c00000)
to space 10240K, 0% used [0x00000000f8800000, 0x00000000f8800000, 0x00000000f9200000)
concurrent mark-sweep generation total 102400K, used 3847K [0x00000000f9c00000, 0x0000000100000000, 0x0000000100000000)
Metaspace used 3330K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 359K, capacity 388K, committed 512K, reserved 1048576K
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)