12、JVM实战:内存分配策略:动态对象年龄判定

12–内存分配策略–动态对象年龄判定


1、动态对象年龄判定

如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。

2、测试

2.1、代码

public class Test {
    private static final int _1MB = 1024 * 1024;

  //参数
  //-verbose:gc
  //-Xms20M
  //-Xmx20M
  //-Xmn10M
  //-XX:+PrintGCDetails
  //-XX:SurvivorRatio=8
  //-XX:MaxTenuringThreshold=15     
  //-XX:+PrintTenuringDistribution   
  //-XX:+UseSerialGC
    public static void main(String[] args) {
         byte[] allocation1, allocation2, allocation3, allocation4;  
         
         allocation1 = new byte[_1MB / 4];  
       
         allocation2 = new byte[_1MB / 4];  
         // allocation1+allocation2大于survivor空间的一半 ,进入老年代
         allocation3 = new byte[4 * _1MB];  
         allocation4 = new byte[4 * _1MB];  
         allocation4 = null;  
         allocation4 = new byte[4 * _1MB];  
      
    }
}

2.1、日志

 
[GC[DefNew
Desired survivor size 524288 bytes, new threshold 1 (max 15)
- age   1:    1003080 bytes,    1003080 total
: 5279K->979K(9216K), 0.0055052 secs] 5279K->5075K(19456K), 0.0055649 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC[DefNew
Desired survivor size 524288 bytes, new threshold 15 (max 15)
- age   1:        256 bytes,        256 total
: 5403K->0K(9216K), 0.0024450 secs] 9499K->5075K(19456K), 0.0024776 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 def new generation   total 9216K, used 4260K [0x00000000f9a00000, 0x00000000fa400000, 0x00000000fa400000)
  eden space 8192K,  52% used [0x00000000f9a00000, 0x00000000f9e28fd0, 0x00000000fa200000)
  from space 1024K,   0% used [0x00000000fa200000, 0x00000000fa200100, 0x00000000fa300000)
  to   space 1024K,   0% used [0x00000000fa300000, 0x00000000fa300000, 0x00000000fa400000)
 tenured generation   total 10240K, used 5075K [0x00000000fa400000, 0x00000000fae00000, 0x00000000fae00000)
   the space 10240K,  49% used [0x00000000fa400000, 0x00000000fa8f4c10, 0x00000000fa8f4e00, 0x00000000fae00000)
 compacting perm gen  total 21248K, used 2540K [0x00000000fae00000, 0x00000000fc2c0000, 0x0000000100000000)
   the space 21248K,  11% used [0x00000000fae00000, 0x00000000fb07b358, 0x00000000fb07b400, 0x00000000fc2c0000)
No shared spaces configured.

3、分析

即使MaxTenuringThreshold=15,会发现运行结果中Survivor的空间占用仍然为0%,而老年代比预期增加了9%,也就是说allocation1、allocation2对象都直接进入了老年代,而没有等到15岁的临界年龄。因为这两个对象加起来已经达到了0.5M,并且它们是同年的,满足同年对象达到Survivor空间的一半规则。我们只要注释掉其中一个对象的new操作,就会发现另外一个不会晋升到老年代中去。

3、分析

3.1、第1次GC

allocation1对象和allocation2对象以及allocation3对象都可以存放进Eden区,当allocation4对象申请分配的时候空间不足,这时进行第一次GC回收。

3.1.1、日志解读


[GC[DefNew
Desired survivor size 524288 bytes, new threshold 1 (max 15)
- age   1:    1003080 bytes,    1003080 total
: 5279K->979K(9216K), 0.0055052 secs] 5279K->5075K(19456K), 0.0055649 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
GC :

代表发生了一次垃圾回收,前面没有Full修饰,表明这时一次Minor GC;

new threshold 1 (max 15)

当前对象的年龄为1,最大年龄为15

5279K->979K(9216K)

三个参数分别为:GC前该内存区域(这里是年轻代)使用容量,GC后该内存区域使用容量,该内存区域总容量。

5279K->5075K(19456K)

三个参数分别为:堆区垃圾回收前的大小,堆区垃圾回收后的大小,堆区总大小。

0.0055649 secs

代表本次新生代GC耗时

年轻代回收空间

5279K-979K=4300K=4.1992M

堆回收空间

5279K-5075K=204K

进入老年代空间

4300K-204K=4096=4M

GC前其他对象空间

5279K-4*1024- (1024/4)*2=671K

GC后其他对象空间

979K-512K=464K

3.1.2、 内存变化图

*

allocation1对象和allocation2对象进入s1区,大对象allocation3直接进入老年代

*

3.1、第2次GC

allocation4 = null;
allocation4 = new byte[4 * _1MB];

当执行上面代码时候,触发第二次GC,但是由于a1+a2这两个对象加起来已经到达了512KB,并且它们是同年龄的,满足同年对象达到Survivor空间一半的规则。根据动态年龄判断规则,这时直接进入老年代

*

3.1.1、日志解读


[GC[DefNew
Desired survivor size 524288 bytes, new threshold 15 (max 15)
- age   1:        256 bytes,        256 total
: 5403K->0K(9216K), 0.0024450 secs] 9499K->5075K(19456K), 0.0024776 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
GC :

代表发生了一次垃圾回收,前面没有Full修饰,表明这时一次Minor GC;

new threshold 1 (max 15)

当前对象的年龄为1,最大年龄为15

5403K->0K(9216K)

三个参数分别为:GC前该内存区域(这里是年轻代)使用容量,GC后该内存区域使用容量,该内存区域总容量。

9499K->5075K(19456K)

三个参数分别为:堆区垃圾回收前的大小,堆区垃圾回收后的大小,堆区总大小。

0.0024450 secs

代表本次新生代GC耗时

年轻代回收空间

5403K-0K=5403K=5.276M

堆回收空间

9499K-5075K=4424K

进入老年代空间

5403K-4424K=979K
其中464K是第1次GC中留下的其他对象。也就是说除此之外还有979K-464K=512K进入老年代
也就是a1+a2的值