JVM--基础--12--内存分配策略--动态对象年龄判定

本文深入解析JVM内存管理中的动态对象年龄判定机制,通过实例展示了当对象总大小超过Survivor区域50%时,年龄达到一定值的对象将直接进入老年代。通过代码测试和日志分析,解释了如何在Minor GC后调整对象晋升策略,以优化内存使用和提升性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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


1、动态对象年龄判定

1.1、定义

当前存放对象的Surnvivor区域里(其中一块区域,存放对象的那块s区),一批对象的总大小大于这块Sunvivor区域内存大小的50%(由-XX:TargetSurvivorRatio参数指定),那么此时大于等于这批对象年龄最大值的对象,就可以直接进入老年代了。

这个规则其实是希望那些可能是长期存活的对象,尽早进入老年代。
对象动态年龄判断机制一般是在minor gc之后触发的。

1.2、举例

Survivor区域里现在有一批对象,年龄1+年龄2+年龄3+…+ 年龄n的多个年龄对象总和超过了Survivor区域的50%,此时就会把年龄n(含)以上的对象都放入老年代。

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%(40%+9%),也就是说allocation1、allocation2对象都直接进入了老年代,而没有等到15岁的临界年龄,因为这两个对象加起来已经达到了0.5M,满足总存活对象大小达到Survivor空间的一半规则。我们只要注释掉其中一个对象的new操作,就会发现另外一个不会晋升到老年代中去。

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对象在s1区放不下,直接进入老年代

在这里插入图片描述

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的值

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值