代码清单3-8 动态对象年龄判定《深入理解Java虚拟机》周志明

为了能更好地适应不同程序的内存状况,虚拟机并不是永远地要求对象的年龄必须达到了MaxTenuringThreshold才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。

执行代码清代3-8中的testTenuringThreshold2()方法,并设置-XX:MaxTenuringThreshold=15,会发现运行结果中Survivor的空间占用仍然为0%,而老年代比预期增加6%,也就是说,allocation1、allocation2对象直接进入了老年代,而没有等到15岁的临界年龄。因为这两个对象加起来已经达到了512KB,并且它们是同年的,满足同年对象达到Survivor空间的一半规则。我们只要注释掉其中一个对象new操作,就会发现另外一个不会晋升到老年代中去了。

代码清单3-8 动态对象年龄判定:

package lime.jvm._003._006._004;

/**
 * @Author : Liangmy
 * @Description :
 * @Date : Created in 2020/1/5 下午9:50
 * @Modified By :
 * VM Args : -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -XX:+UseSerialGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintTenuringDistribution
 * java -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -XX:+UseSerialGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintTenuringDistribution lime.jvm._003._006._004.TestTenuringThreshold2
 */
public class TestTenuringThreshold2 {
    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) {
        testTenuringThreshold2();
    }

    private static void testTenuringThreshold2() {
        byte[] allocation1, allocation2, allocation3, allocation4;
        // eden(8MB) 0MB from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB)
        allocation1 = new byte[_1MB / 4]; // eden(8MB) 0.25MB(0) from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB)
        // allocation1 + allocation2 大于 survivor 空间的一半
        allocation2 = new byte[_1MB / 4]; // eden(8MB) 0.25MB(0) 0.25MB(0) from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB) 0MB
        allocation3 = new byte[_1MB * 4]; // eden(8MB) 0.25MB(0) 0.25MB(0) 4MB(0) from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB) 0MB
        // allocation1 + allocation2 + allocation3 + allocation4 大于 eden
        // 触发GC
        // allocation1、allocation2 进入survivor,但是allocation1 + allocation2 大于 survivor 空间的一半,allocation1、allocation2对象都直接进入了老年代
        // allocation3 大于survivor,直接进入老年代
        // eden(8MB) 0MB from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB) 4.5MB
        // 手动调用GC测试 System.gc();
        allocation4 = new byte[_1MB * 4]; // eden(8MB) 4MB(0) from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB) 4.5MB(和预想中的不一样)
        allocation4 = null;
        // 4MB(不可达) + 4MB 大于 eden
        // 触发GC,eden(8MB) 0MB from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB) 4.5MB
        allocation4 = new byte[_1MB * 4]; // eden(8MB) 4MB from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB) 4.5MB
    }
}

运行结果:

本地测试结果:

localhost:_004 liangmy$ java -version
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)
localhost:_004 liangmy$ java -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -XX:+UseSerialGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintTenuringDistribution lime.jvm._003._006._004.TestTenuringThreshold2
[GC (Allocation Failure) [DefNew
Desired survivor size 524288 bytes, new threshold 1 (max 15)
- age   1:     809360 bytes,     809360 total
: 5279K->790K(9216K), 0.0050284 secs] 5279K->4886K(19456K), 0.0050733 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (Allocation Failure) [DefNew
Desired survivor size 524288 bytes, new threshold 15 (max 15)
: 4886K->0K(9216K), 0.0014409 secs] 8982K->4884K(19456K), 0.0014642 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 def new generation   total 9216K, used 4178K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)
  eden space 8192K,  51% used [0x00000007bec00000, 0x00000007bf014930, 0x00000007bf400000)
  from space 1024K,   0% used [0x00000007bf400000, 0x00000007bf400000, 0x00000007bf500000)
  to   space 1024K,   0% used [0x00000007bf500000, 0x00000007bf500000, 0x00000007bf600000)
 tenured generation   total 10240K, used 4884K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)
   the space 10240K,  47% used [0x00000007bf600000, 0x00000007bfac5290, 0x00000007bfac5400, 0x00000007c0000000)
 Metaspace       used 2646K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 286K, capacity 386K, committed 512K, reserved 1048576K

 

思考:

allocation4 = new byte[_1MB * 4]; // eden(8MB) 4MB(0) from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB) 4.5MB(和预想中的不一样)

???愁人。。。

code : 

package lime.jvm._003._006._004;

/**
 * @Author : Liangmy
 * @Description :
 * @Date : Created in 2020/1/5 下午9:50
 * @Modified By :
 * VM Args : -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -XX:+UseSerialGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintTenuringDistribution
 * java -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -XX:+UseSerialGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintTenuringDistribution lime.jvm._003._006._004.TestTenuringThreshold2
 */
public class TestTenuringThreshold2 {
    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) {
        testTenuringThreshold2();
    }

    private static void testTenuringThreshold2() {
        byte[] allocation1, allocation2, allocation3, allocation4;
        // eden(8MB) 0MB from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB)
        allocation1 = new byte[_1MB / 4]; // eden(8MB) 0.25MB(0) from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB)
        // allocation1 + allocation2 大于 survivor 空间的一半
        allocation2 = new byte[_1MB / 4]; // eden(8MB) 0.25MB(0) 0.25MB(0) from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB) 0MB
        allocation3 = new byte[_1MB * 4]; // eden(8MB) 0.25MB(0) 0.25MB(0) 4MB(0) from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB) 0MB
        // allocation1 + allocation2 + allocation3 + allocation4 大于 eden
        // 触发GC
        // allocation1、allocation2 进入survivor,但是allocation1 + allocation2 大于 survivor 空间的一半,allocation1、allocation2对象都直接进入了老年代
        // allocation3 大于survivor,直接进入老年代
        // eden(8MB) 0MB from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB) 4.5MB
        // 手动调用GC测试 System.gc();
        allocation4 = new byte[_1MB * 4]; // eden(8MB) 4MB(0) from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB) 4.5MB(和预想中的不一样)
//        allocation4 = null;
        // 4MB(不可达) + 4MB 大于 eden
        // 触发GC,eden(8MB) 0MB from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB) 4.5MB
//        allocation4 = new byte[_1MB * 4]; // eden(8MB) 4MB from survivor(1MB) 0MB to survivor(1MB) 0MB tenure gen(10MB) 4.5MB
    }
}

GC log : 

??? 愁人。。。 

在为allocation4分配空间之前先手动调用GC的话,符合猜想。。。so.why?

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值