java 内存 新生代 老年代_Java中内存分配和回收策略、新生代、老年代

Java中对于垃圾回收的策略有多种,而目前商业虚拟机的垃圾收集都采用“分代收集”,这种算法是根据对象存活周期的不一样将内存分为几块,通常是将Java堆分为新生代和老年代,根据各个年代的特色采用较适合的收集算法。java

新生代中采用的收集算法:复制算法。算法的思想是将可用内存分为大小相等的两块,每次使用其中一块,当一块内存用完了,就将还存活的对象分到另外一块。而后把使用过的内存空间一次进行清理。这种算法缺点会明显,就是会浪费一半的空间。而根据IBM研究代表,新生代中98%的对象朝生夕死,因此不须要按照1:1进行分配,而是按照内存分为一块较大的Eden空间和两块较小的Survivor空间(from和to两个),每次使用Eden和其中一个Survivor。当回收时,将Eden和其中一块Survivor中还存活着的对象一次性复制到另外一块Survivor中,而后清理Eden和刚才用过的Survivor空间。通常默认的比例为:Eden:from:to=8:1:1。注:可经过-XX:SurvivorRatio=i来设置,默认i=8。当Survivor空间不够时,须要依赖其余内存(老年代)进行分配担保。内存的分配担保:若是另外一块Survivor空间没有足够的内存空间存放上一次新生代收集下来的存活对象,那么这些对象将直接经过分配担保机制进入老年代。算法

老年代中采用的收集算法:标记-整理算法。算法思想:首先标记须要回收的对象,而后让全部存活的对象向一端移动,而后直接清理掉边界之外的内存。数组

内存分配及回收策略安全

一、对象优先在Eden分配:大多数状况下,对象在新生区Eden区中分配,当Eden没有足够空间分配时,虚拟机将发起一次Minor GC(见如下代码注释),GC后将已有对象放入Survivor中,若Survivor空间不足,则经过分配担保机制提早转移到老年代。spa

public class TestMinorGc {

private static final int _1M=1024*1024;

/**

* VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGcDetails -XX:SurvivorRatio=8

*

* 上述在参数在运行程序时配置。-Xms20M -Xmx20M设置堆大小为20M -Xmn10M:堆中新生代10M。

*

* -XX:SurvivorRatio=8:Eden占8M。-XX:PrintGcDetails:这个参数告诉虚拟机在发生垃圾

*

* 收集行为时打印内存回收日志。

*

* */

public static void testAllocation(){

byte[] a1,a2,a3,a4;

a1=new byte[2*_1M];

a2=new byte[2*_1M];

a3=new byte[2*_1M];

/** 在Eden中为a4分配内存时,发现只剩下2M,内存不够,这时会发生一次Minor GC(Minor GC指发生在新生代的

* 垃圾收集动做,频率较高。引伸:老年代GC(Major GC/Full Gc):发生在老年代的GC,速度慢,通常是Minor

* 的1/10.)GC后发现已有的3个2M的对象没法放入Survivor中(空间不够),所以须要使用分配担保机制将它们提早

* 转移到老年代中。

* */

a4=new byte[4*_1M];

}

}

二、大对象直接进入老年代。所谓大对象是指须要大量连续内存空间的Java对象,例如较长的字符串和较长的数组。虚拟机提供了一个-XX:PretenureSizeThreshold参数,令大于这个值的参数直接在老年代分配。

public class BigObjectOld {

private static final int _1M = 1024 * 1024;

/**

* VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGcDetails

* -XX:SurvivorRatio=8 -XX:PretenureSizeThreshold=3145728

*

* 注意:-XX:PretenureSizeThreshold后面的参数不能写3M,而要写3145728。

*/

public static void testBigObjectOld(){

byte[] a;

/**

* a所占内存大于设置的参数,故直接进入老年代。

* */

a=new byte[4*_1M];

}

}

三、长期存活的对象进入老年代。虚拟机既然采用了分代收集的思想来管理内存,那么内存回收时就必须能识别对象放在新生代,哪些对象放在老年代。为了作到这点,虚拟机给每一个对象定义一个对象年龄计数器。若是对象在Eden出生并通过第一次MinorGC而后仍然存活,而且能被Survivor容纳的话,将被移到Survivor中,而且对象年龄设为1。对象在Survivor中没过一次Minor GC,年龄就增长一岁。当年龄增长到必定程度,就会晋升到老年代。对象晋升老年代的年龄阈值,能够经过参数:-XX:MaxTenuringThreshold设置。

四、动态对象年龄断定。为了能更好的适应不一样程序的内存情况,虚拟机并非永远的要求对象必须达到MaxTenuringThreshold才能晋升老年代,若是在Survivor空间中相同年龄全部对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就能够直接进入老年代,无需达到MaxTenuringThreshold的要求。日志

五、空间分配担保。在发生Minor GC以前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代全部对象的总空间,若是这个条件成立,那么Minor GC能够确保是安全的。若不成立,则虚拟机会查看HandlePromotionFailure设置值是否担保失败,若容许,那么会继续检查老年代最大可用连续空间是否大于历次晋升到老年代对象的平均大小(至关于一个经验值,不保证能够成功),若是大于,,尽管此次Minor GC冒险,也会尝试进行一次Minor GC;若是小于,或者HandlePromotionFailure设置为不容许冒险,那么须要进行一次Full GC。code

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值