深入理解Java虚拟机(4)——对象的内存分配

对象基本上是在堆上分配(除了JIT即时编译器优化),分配规则如下:

  • 主要分配在新生代的Eden区上;

  • 若开启了本地线程分配缓冲TLAB,按线程优先在TLAB上分配;

  • 少数情况直接分配在老年代

 

1、对象优先在Eden上分配

 

目前主流的GC都采用了分代回收算法,因此将内存分为了新生代和老年代。新生代一般采取“复制”算法,考虑效率和避免内存碎片的问题。

 

堆内存的新生代被进一步分为:Eden+From Survivor+To Survivor。

  • 对象首先分配在Eden区;

  • 若Eden区放不下这个对象时,会触发一次Minor GC,回收Eden + From Survivor中无效的对象,并将存活的对象放置于To Survivor中;

  • 若To Survivor空间放不下存活对象,就会启用“分配担保”,将这些存活对象转移至老年代中,然后再将新对象存入Eden区。

 

2、大对象直接进入老年代

 

大对象是指,需要大量连续内存空间的Java对象,比如:很长的字符串及数组。

 

我们知道:一个大对象能存入Eden区+Survivor1区的概率较小,发生分配担保概率较大,而分配担保涉及大量的复制操作,导致效率低下。

 

解决:将大对象直接放到老年代,从而避免大量复制操作。

 

通过-XX:PretrnureSizeThreshold参数设置大对象

 

该参数用于设置大小超过该参数的对象被认为是“大对象”,直接进入老年代。

注意:该参数只对Serial和ParNew收集器有效。

 

3、长期存活的对象将进入老年代

 

老年代用于存储生命周期较长的对象,那么如何判断一个对象的年龄?

 

新生代的每个对象都有一个对象年龄计数器,

  • 对象在Eden出生,每经过一次Minor GC还存活,对象年龄就加一;

  • 当年龄超过一定值时,就将超过该值的新生代对象转移到老年代。

 

使用-XX:MaxTenuringThreshold参数设置新生代的最大年龄

 

只要超过该值,对象就会转移到老年代中。

 

动态对象年龄判断

 

目的:为了更好适应不同程序的内存状况

 

如果在当前新生代的Survivor中,年龄相同的对象的内存空间总和超过了Survivor内存空间的一半,那么年龄大于或者等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。

 

4、空间分配担保

 

发生Minor GC之前,虚拟机首先会检查“老年代中最大连续区域的大小  是否大于  新生代中所有对象的总大小”,

也就是说老年代目前能否一定能将新生代中的所有对象全部装下?

 

  • 若能装下,此时进行Minor GC没有任何风险,然后进行Minor GC;

  • 若不一定能装下,此时进行Minor GC是有风险的,检查HandlePromotionFailure设置值是否允许担保失败,

    • 若允许,那么检查老年代最大可用的连续空间  是否大于   历次晋升到老年代对象的平均大小;

      • 若大于,尝试进行Minor GC,尽管这次Minor  GC是有风险的;

      • 若小于,改为进行一次Full GC。

    • 不允许,改为进行一次Full GC,清除老年代的废弃数据来扩大老年代的空闲空间,以便给新生代作分配担保。

 

“风险”是指什么?

 

  • 新生代使用“复制”算法,需要分配担保;而老年代使用的是“标记-整理”算法,不需要。

  • 在Minor GC后,当Survivor内存不够时,老年代要进行担保,必须要有足够空间存放存活对象;

  • 但是有多少对象活下来在回收之前时不知道的,所以取 “历次晋升到老年代对象的平均大小”作为经验值,决定是否用Full GC来让老年代腾出更多空间;

  • 若最终还是担保失败了,那么失败之后重新发起一次Full GC。为了防止Full GC过于频繁,HandlePromotionFailure一般设置为打开。

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值