jvm学习记录--06 垃圾回收对象内存分配策略

来源:互联网 发布:港融数据大平台主页 编辑:程序博客网 时间:2024/05/16 17:18

堆内存分配示意图

这里写图片描述

对象优先进入Eden

HotSpot虚拟机新生代内存布局及算法
(1)、将新生代内存分为一块较大的Eden空间和两块较小的Survivor空间;
(2)、每次使用Eden和其中一块Survivor;
(3)、当回收时,将Eden和使用中的Survivor中还存活的对象一次性复制到另外一块Survivor;
(4)、而后清理掉Eden和使用过的Survivor空间;
(5)、后面就使用Eden和复制到的那一块Survivor空间,重复步骤3;
默认Eden:Survivor=8:1,即每次可以使用90%的空间,只有一块Survivor的空间被浪费;
大多数情况下,对象在新生代Eden区中分配;
当Eden区没有足够空间进行分配时,JVM将发起一次Minor GC(新生代GC);
Minor GC时,如果发现存活的对象无法全部放入Survivor空间,只好通过分配担保机制提前转移到老年代。

  • Minor GC 又称新生代GC,指发生在新生代的垃圾收集动作; 因为Java对象大多是朝生夕灭,所以Minor
    GC非常频繁,一般回收速度也比较快;
  • Full GC又称Major GC或老年代GC,指发生在老年代的GC,出现Full GC经常会伴随至少一次的Minor
    GC(不是绝对,Parallel Sacvenge收集器就可以选择设置Major GC策略),Major GC速度一般比Minor
    GC慢10倍以上;

大对象直接进入老年代

大对象指需要大量连续内存空间的Java对象,如,很长的字符串、数组等经常出现大对象容易导致内存还有不少空间就提前触发GC,以获取足够的连续空间来存放它们,所以应该尽量避免使用创建大对象,让大对象直接进入老年代还可以避免Survivor中两个空间的拷贝.-XX:PretenureSizeThreshold=3145728 可以设置这个阈值,大于这个参数值的对象直接在老年代分配,这里设置的是大于3M。  默认值是 0 (无效),并且且只对Serail和ParNew两款收集器有效;如果需要使用该参数,可考虑ParNew+CMS组合

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

JVM给每个对象定义一个对象年龄计数器,其计算流程如下:

    在Eden中分配的对象,经Minor GC后还存活,就复制移动到Survivor区,年龄为1;    而后每经一次Minor GC后还存活,在Survivor区复制移动一次,年龄就增加1岁;    如果年龄达到一定程度,就晋升到老年代中;
-XX:MaxTenuringThreshold设置新生代对象晋升老年代的年龄阈值,默认为15

动态对象年龄判定

 JVM为更好适应不同程序,不是永远要求等到MaxTenuringThreshold中设置的年龄; 如果在Survivor空间中相同年龄的所有对象大小总和大于Survivor空间的一半,大于或等于该年龄的对象就可以直接进入老年代;

空间分配担保

当Survivor空间不够用时,需要依赖其他内存(老年代)进行分配担保(Handle Promotion)

分配担保的流程如下:

     在发生Minor GC前,JVM先检查老年代最大可用的连续空间是否大于新生所有对象空间;       如果大于,那可以确保Minor GC是安全的;       如果不大于,则JVM查看HandlePromotionFailure值是否允许担保失败;       如果允许,就继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小;       如果大于,将尝试进行一次Minor GC,但这是有风险的;       如果小于或HandlePromotionFailure值不允许冒险,那这些也要改为进行一次Full GC;

尝试Minor GC的风险–担保失败:

    因为尝试Minor GC前面,无法知道存活的对象大小,所以使用历次晋升到老年代对象的平均大小作为经验值;    假如尝试的Minor GC最终存活的对象远远高于经验值的话,会导致担保失败(Handle Promotion Failure);    失败后只有重新发起一次Full GC,这绕了一个大圈,代价较高;    但一般还是要开启HandlePromotionFailure,避免Full GC过于频繁,而且担保失败概率还是比较低的;

JDK6-u24后,JVM代码中已经不再使用HandlePromotionFailure参数了;
规则变为:

只要老年代最大可用的连续空间大于新生所有对象空间或历次晋升到老年代对象的平均大小,就会进行Minor GC;否则进行Full GC;即老年代最大可用的连续空间小于新生所有对象空间时,不再检查HandelPromotionFailure,而直接检查历次晋升到老年代对象的平均大小;    
原创粉丝点击