GC发生时内存分配和回收策略

在《深入理解java虚拟机》一书中读到3.6章节,内存分配和回收策略:
预备知识
java堆=年轻代(Eden+Survivor+Survivor)+老年代
Eden:Survivor:Survivor默认比例8:1:1,每次年轻代使用率90%(Eden和一个Survivor)。
一 内存分配策略
1 对象优先在eden分配
可用空间是Eden和一个Survivor,在GC回收发生时,如果存活的对象比另一个survivor空间要大,就直接放到老年代和survivor中,这部分称为分配担保。
2 大对象直接进入老年代
可以通过设置参数,将大对象直接存入老年代,防止了大对象来回复制造成的损失。
3 长期存活的对象将进入老年代
对象在Eden中出生后,并经历过一次GC后仍存活,且被survivor容纳的话,被移动到survivor空间,并记年龄为1岁,对象在每经历一次MinorGC后,年龄都增加1岁,当年龄到达一定程度就会转到老年代,用XX:MaxTenuringThreshold参数进行设置。
下面是对第三节一段代码的理解。

/* 参数设置为
-Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails 
-XX:MaxTenuringThreshold=1
*/
public class TestAllocation {

    private static final int _1MB = 1024*1024; 

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        testTenuringThreshold();
    }
    public static void testTenuringThreshold(){
        byte[] all1,all2,all3;
        all1 = new byte[ _1MB/4];
        //什么时候进入老年代取决于XX:MaxTenuringThreshold设置
        all2 = new byte[4* _1MB];
        all3 = new byte[4* _1MB];
        all3 = null;
        //all3 = new byte[4* _1MB];
    }
}

上述代码运行结果
1次GC
如果把注释去掉

//all3 = new byte[4* _1MB];

结果是如下
2次GC

二 结果分析
那么为什么会这样,下面分析内存变化
图1 是执行如下两行后结果

        all1 = new byte[ _1MB/4];
        all2 = new byte[4* _1MB];

图2

        all3 = new byte[4* _1MB];

要给all3分配内存,没空间,进行第一次GC,再在Eden分配空间给all3
图3

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

又要分配新内存4M,没空间,所以进行第二次GC,原来的4M空间的all3引用不再指向它,按理这次GC被回收,图3是进行GC后的图,Eden区因为没有引用指向它被回收,而Survivor2变量因达到优年轻代转向老年代阈值,而被复制到老年代。
可以从GC日志中看出,第二次GC后
[GC[DefNew: 4905K->0K(9216K), 0.0006405 secs],年轻代成为空。
图4
是给all3分配内存的图。所以第二个程序最终结果是图3,而第一个程序最终结果是图2。

内存分析

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值