关于这一段代码 有几个不是让人很理解的地方,我一一说来。
1.Desired survivor size 524288 bytes
关于这个512KB空间是怎么来的,JVM有这样一个参数:
-XX:TargetSurvivorRatio:目标存活率,默认为50%,表明所有age的survivor space对象的大小如果超过Desired survivor size,则重新计算threshold,以age和MaxTenuringThreshold的最小值为准,否则以MaxTenuringThreshold为准.
简单的说,如果要分配的Survivor空间是1M那么,desired survivor size 就是512KB,这个大小影响的是Tenuring Threshold参数
当你试图放入800KB的对象是,Survivor from是运行你放入的,但是Tenuring Threshold大小会变成1(就算你之前是15,这里也会动态改成1),即下次GC发生时,age=1的统统放入老年代
2.Eden,Survivor from,to的关系
对象分配空间的时候,若Eden仍有区域时,都会将对象放置Eden,持续新增对象一段时间后,Eden无法容纳时,这个时候就会发生一次Minor GC。
当发生Minor GC时,会将Eden和 Survivor from中的幸存对象存放在Survivor to中,同时这些对象的age+1。
若Survivor to无法容纳幸存对象,就将无法容纳的对象放置在永久带中。
当GC时,存在对象的age=Tenuring Threshold时,不管Survivor to是否空间足够,都将他们放入永久代。
发生GC的前提,放入对象时空间不够,放入对象后空间占用完毕。
这段例子中,当XX:MaxTenuringThreshold=1时
a1 = 0.25M,a2=4M;
分配a3=4M时,Eden无法容纳4M的对象了,发起Minor GC,此时a1,a2 age=1,
这个时候,Survivor最大容量1M,无法同时容纳存活的4.5M a1,a2
虚拟机将4M的a2放入老年代,同时将0.25M的a1放入Survivor to中,此时空间分布Eden(0M),Survivor from(0.25M),Old(4M)
放入4M的a3,此时空间分布Eden(4M),Survivor from(0.25M),Old(4M)
a3=null;只是说明了a3无引用,但是数组空间仍然存在,只是提示jvm我下次可以被回收了
a3=4M,又分配了4M的空间,这个时候Eden 4+4=8M 已经满了,触发一次GC(这时,jvm会清理age=1的对象,a1,a2被放在了老年代)
发现之前创建的4M数组没有GC Root相关联,而且不符合自救规则,回收。
此时空间分布Eden(4M),Survivor from(0M),Old(4.25M)
/** * VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=1 -XX:+PrintTenuringDistribution * */ @SuppressWarnings("unused") public static void testTenuringThreshold() { byte[] allocation1, allocation2, allocation3; allocation1 = new byte[_1MB / 4]; //262144 什么时候进入老年代决定于XX:MaxTenuringThreshold设置 allocation2 = new byte[4 * _1MB]; //4194304 allocation3 = new byte[4 * _1MB]; allocation3 = null; allocation3 = new byte[4 * _1MB]; /** * * XX:MaxTenuringThreshold=1 [GC [DefNew Desired survivor size 524288 bytes, new threshold 1 (max 1) - age 1: 418144 bytes, 418144 total : 4695K->408K(9216K), 0.0054252 secs] 4695K->4504K(19456K), 0.0054708 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] [GC [DefNew Desired survivor size 524288 bytes, new threshold 1 (max 1) - age 1: 136 bytes, 136 total : 4668K->0K(9216K), 0.0013601 secs] 8764K->4504K(19456K), 0.0013867 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] Heap def new generation total 9216K, used 4260K [0x32750000, 0x33150000, 0x33150000) eden space 8192K, 52% used [0x32750000, 0x32b78fe0, 0x32f50000) from space 1024K, 0% used [0x32f50000, 0x32f50088, 0x33050000) to space 1024K, 0% used [0x33050000, 0x33050000, 0x33150000) tenured generation total 10240K, used 4504K [0x33150000, 0x33b50000, 0x33b50000) the space 10240K, 43% used [0x33150000, 0x335b60a0, 0x335b6200, 0x33b50000) compacting perm gen total 12288K, used 377K [0x33b50000, 0x34750000, 0x37b50000) the space 12288K, 3% used [0x33b50000, 0x33bae5c0, 0x33bae600, 0x34750000) ro space 10240K, 55% used [0x37b50000, 0x380d1140, 0x380d1200, 0x38550000) rw space 12288K, 55% used [0x38550000, 0x38bf44c8, 0x38bf4600, 0x39150000) */ }
这段例子中,当XX:MaxTenuringThreshold=8时
a1 = 0.25M,a2=4M;
分配a3=4M时,Eden无法容纳4M的对象了,发起Minor GC
这个时候,Survivor最大容量1M,无法同时容纳存活的4.5M a1,a2
虚拟将4M的a2放入老年代,同时将0.25M的a1放入Survivor to中,此时空间分布Eden(0M),Survivor from(0.25M),Old(4M)
放入3M的a3,此时空间分布Eden(4M),Survivor from(0.25M),Old(4M)
a3=null;只是说明了a3无引用,但是数组空间仍然存在,只是提示jvm我下次可以被回收了
a3=4M,又分配了4M的空间,这个时候Eden 4+4=8M 已经满了,触发一次GC
发现之前创建的4M数组没有GC Root相关联,而且不符合自救规则,回收。
此时空间分布Eden(4M),Survivor from(0.25M),Old(4M)
/** * * XX:MaxTenuringThreshold =8 [GC [DefNew Desired survivor size 524288 bytes, new threshold 8 (max 8) - age 1: 418144 bytes, 418144 total : 4695K->408K(9216K), 0.0036693 secs] 4695K->4504K(19456K), 0.0036983 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC [DefNew Desired survivor size 524288 bytes, new threshold 8 (max 8) - age 1: 136 bytes, 136 total - age 2: 417936 bytes, 418072 total : 4668K->408K(9216K), 0.0010034 secs] 8764K->4504K(19456K), 0.0010296 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] Heap def new generation total 9216K, used 4668K [0x32750000, 0x33150000, 0x33150000) eden space 8192K, 52% used [0x32750000, 0x32b78fe0, 0x32f50000) from space 1024K, 39% used [0x32f50000, 0x32fb6118, 0x33050000) to space 1024K, 0% used [0x33050000, 0x33050000, 0x33150000) tenured generation total 10240K, used 4096K [0x33150000, 0x33b50000, 0x33b50000) the space 10240K, 40% used [0x33150000, 0x33550010, 0x33550200, 0x33b50000) compacting perm gen total 12288K, used 377K [0x33b50000, 0x34750000, 0x37b50000) the space 12288K, 3% used [0x33b50000, 0x33bae5b8, 0x33bae600, 0x34750000) ro space 10240K, 55% used [0x37b50000, 0x380d1140, 0x380d1200, 0x38550000) rw space 12288K, 55% used [0x38550000, 0x38bf44c8, 0x38bf4600, 0x39150000) */