Java虚拟机-内存分配策略

Java技术体系中所提倡的自动内存管理策略最终能够归结为自动化地解决了两个问题:给对象分配内存以及回收分配给对象的内存;算法

几条广泛的分配规则:
一、对象优先在Eden区分配
年轻代分为三个区:1个Eden区+2个Survivor区。
大部分对象在Eden区中生成(大对象能够直接被建立在年老代),还存活的对象将被复制到一个Survivor区,当这个Survivor区满时,此区的存活对象将被复制到剩下的一个Survivor区中,当这个Survivor区也满了的时候,从第一个Survivor复制过来的而且此时还存活的对象,将被复制到年老区。
须要注意的是,Survivor的两个区是对称的,没前后关系,因此同一个区中可能同时存在从Eden区复制过来的对象和从前一个Survivor区复制过来的对象,而复制到年老区的就只有从第一个Survivor区过去的对象。而且Survivor区总有一个是空的。
Minor GC(Young GC)对象被建立时,内存的分配首先发生在年轻代,大部分的对象在建立后很快就再也不使用,所以很快变得不可达,因而被年轻代的GC机制清理掉,这个GC机制被称为Minor GC或Young GC。
注意Minor GC并不表明年轻代内存不足,它事实上只表示在Eden区上的GC。
因为绝大部分对象都是短命的,甚至存活不到Survivor区中,因此Eden与Survivor的比例较大,HotSpot默认为8:1.数组

在Eden区,HotSpot虚拟机使用了两种技术来加快内存分配。分别是bump-the-pointer和TLAB(Thread- Local Allocation Buffers),这两种技术的作法分别是:因为Eden区是连续的,所以bump-the-pointer技术的核心就是跟踪最后建立的一个对象,在对象建立时,只须要检查最后一个对象后面是否有足够的内存便可,从而大大加快内存分配速度;而对于TLAB技术是对于多线程而言的,将Eden区分为若干段,每一个线程使用独立的一段,避免相互影响。TLAB结合bump-the-pointer技术,将保证每一个线程都使用Eden区的一段,并快速的分配内存;安全

 

二、大对象直接分配在老年代
所谓的大对象是指的须要大量连续内存空间的Java对象。好比:那种很长的字符串以及数组。
常常出现大对象容易致使内存还有很多空间时就提早触发垃圾收集以获取足够的连续空间来“安置”它们;
年老代存放从年轻代存活的对象。通常来讲年老代存放的都是生命周期较长的对象。
年老代的空间通常比年轻代大,能存放更多的对象,在年老代上发生的GC次数也比年轻代少。
当年老代内存不足时,将执行Major GC,也叫Full GC;
可能存在年老代对象引用新生代对象的状况,若是须要执行Young GC,则可能须要查询整个老年代以肯定是否能够清理回收,这显然是低效的。解决的方法是,年老代中维护一个512 byte的块——”card table“,全部老年代对象引用新生代对象的记录都记录在这里。Young GC时,只要查这里便可,不用再去查所有老年代,所以性能大大提升。
通常,老年代用的算法是标记-整理算法,即:标记出仍然存活的对象(存在引用的),将全部存活的对象向一端移动,以保证内存的连续;
多线程

 

在发生Minor GC时,虚拟机会检查每次晋升进入老年代的大小是否大于老年代的剩余空间大小,若是大于,则直接触发一次Full GC,不然,就查看是否设置了-XX:+HandlePromotionFailure(容许担保失败),若是容许,则只会进行MinorGC,此时能够容忍内存分配失败;若是不容许,则仍然进行Full GC(这表明着若是设置-XX:+Handle PromotionFailure,则触发MinorGC就会同时触发Full GC,哪怕老年代还有不少内存,因此,最好不要这样作)。
使用-XX:PretenureSizeThreshold参数,令大于这个设置值的对象直接在老年代分配;这样的目的主要是为了不在Eden区以及2个Survivor区之间发生大量的内存复制;
-XX:PretenureSizeThreshold参数只对Serial 和ParNew 收集器有效,Parallel Sacvenge收集器不认识此参数。
-XX:PretenureSizeThreshold参数的值不能像-Xms同样直接写3M要写成3145728;
性能

 

三、长时间存活的对象分配在老年代
虚拟机采用了分代收集的思想来管理内存,那么内存回收时就必须能识别哪些对象在新生代,哪些对象应在老年代,因此,虚拟机给每一个对象定义了一个对象年龄计数器
若是对象在Eden区出生并经历一次Minor GC后仍然存活,而且能被Survivor区所容纳,那么对象年龄计数器值为1;
对象在Survivor区中每熬过一次Minor GC,年龄就会增长1;
默认年龄是15,能够经过设置-XX:MaxTenuringThreshold来设置。
spa

 

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

 

五、空间分配担保
在发生Minor GC以前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代全部对象的总和。若是条件成立,那么Minor GC能够确保是安全的;
若是不成立,那么虚拟机会查看HandlerPromotionFailure设置值是否容许担保失败。
若是容许,会检查老年代最大可 用的连续空间是否大于历次晋升到老年代对象的平均大小,若是大于,则尝试进行一次Minor GC;若是小于,则会进行一次Full GC
对象

相关文章
相关标签/搜索