【深入理解Java虚拟机】第3章:内存分配与回收策略

1.示例采用的垃圾收集器

本篇使用Serial加Serial Old客户端默认收集组合。
对象分配的规则并不是确定的,取决于虚拟机当前使用的是哪一款垃圾收集器。

2.对象优先在Eden分配

相关博客:垃圾回收:标记复制算法

大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC。

代码

public class test1 {
    public static void main(String[] args) {
        testAllocation();
    }
    public static void testAllocation(){
        /*
        -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -XX:SurvivorRatio=8
        新生代10M,老年代10M
        新生代Eden区与一个Survivor区的空间比例是8:1,Survivor一个1MB
         */
        byte[] allocation1,allocation2,allocation3,allocation4;
        allocation1=new byte[2 * 1024*1024];
        allocation2=new byte[2 * 1024*1024];
        allocation3=new byte[2 * 1024*1024];
        /*
        Eden已被占用6MB,剩余空间已不足以分匹配allocation4需要的4MB,因此发生Minor GC
        又发现三个2M对象不能全部放入Survivor空间(Survivor只有1MB),所以只好通过分配
        担保机制提前转移到老年代去
         */
        allocation4=new byte[4 * 1024*1024];
    }
}

输出
在这里插入图片描述

书上的输出:这段主要是看我对这些输出数据的标注
在这里插入图片描述

3.大对象直接进入老年代

在这里插入图片描述

代码

public class test2 {
    public static void main(String[] args) {
        testPretenureSizeThreshold();
    }
    public static void testPretenureSizeThreshold(){
        /*
        -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:PretenureSizeThreshold=3145728
         */
        byte[] allocation;
        allocation=new byte[4*1024*1024];
    }
}

输出
可以看到直接进入了老年代。
在这里插入图片描述

4.长期存活的对象进入老年代

在这里插入图片描述

代码

public class test3 {
    public static void main(String[] args) {
        testTenuringThreshold();
    }
    public static void testTenuringThreshold(){
        /*
        -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=1
         */
        byte[] allocation1,allocation2,allocation3;
        allocation1=new byte[1024*1024/4];
        allocation2=new byte[4*1024*1024];
        allocation3=new byte[4*1024*1024];
        allocation3=null;
        allocation3=new byte[4*1024*1024];
    }
}

-XX:MaxTenuringThreshold=1 时输出
from space 1024K, 0% used
在这里插入图片描述
-XX:MaxTenuringThreshold=15 时输出
在这里插入图片描述

5.动态对象年龄判定

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

public class test4 {
    /*
    -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -XX:+PrintTenuringDistribution
     */
    public static void main(String[] args) {
        testTenuringThreshold2();
    }
    /*
    alloction1,2都直接进入了老年代,并没等到15岁的临界年龄。
    因为这两个对象加起来已经超过了512KB,并且它们是同年龄的,满足低于或等于某年龄的对象达到Survivor空间一半的规则。
    我们只需要注释掉其中一个对象的new操作,就会发现另外一个就不会晋升到老年代。
     */
    public static void testTenuringThreshold2(){
        byte[] allocation1,allocation2,allocation3,allocation4;
        allocation1=new byte[1024*1024/4];
        allocation2=new byte[1024*1024/4];
        allocation3=new byte[4*1024*1024];
        allocation4=new byte[4*1024*1024];
        allocation4=null;
        allocation4=new byte[4*1024*1024];
    }
}

输出
在这里插入图片描述

6.空间分配担保

JDK6 Update24之后,-XX:HandlePromotionFailure不会影响虚拟机的空间分配担保策略。
只要老年代的连续空间大于新生代对象总大小或者历次晋升的平均大小,就会进行Minor GC,否则将进行Full GC。
在这里插入图片描述
代码

public class test5 {
    private static final int MB=1024*1024;
    public static void main(String[] args) {
        testHandlePromotion();
    }
    /*
    -Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -XX:SurvivorRatio=8
     */
    public static void testHandlePromotion(){
        byte[] allocation1,allocation2,allocation3,allocation4,allocation5,allocation6,allocation7;
        allocation1=new byte[2*MB];
        allocation2=new byte[2*MB];
        allocation3=new byte[2*MB];
        allocation1=null;
        allocation4=new byte[2*MB];
        allocation5=new byte[2*MB];
        allocation6=new byte[2*MB];
        allocation4=null;
        allocation5=null;
        allocation6=null;
        allocation7=new byte[2*MB];
    }
}

输出
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值