`
dmy110
  • 浏览: 846 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
最近访客 更多访客>>
社区版块
存档分类
最新评论

j2se 5.0 hotspot 的四种垃圾回收器

 
阅读更多

以下内容自sun白皮书1-150020中找到,由于加上我自己的理解,所以不是翻译文章(英语不给力,翻译不好).其中我只关注了回收的抽象机制,对于引用计数,具体算法等未涉及.


hotspot(j2se 5.0,按白皮书上的说法也适用于6.0)使用的是所谓的Generational Collection机制,也就是把对象分为young和old(还有一种是permanent,暂时不鸟他),young对象经过几次回收后(存活较长时间后),就会成为old对象.之所以采用这种机制,是基于以下观察:大部分新建对象的引用不会持续太久,也就说是会die young;少部分的引用会持续下来.

因此,young generation 进行Collection会更多,因此使用的算法对时间效率的要求高.old generation 保存的数据较多,使用的算法对空间的要求效率相对而言要求就较高了.把对象分为不同的generation,便于采用不同的算法进行操作.

对应的,可以把HotSpotJVM的内存分为:young generation ,oldgeneration ,permanent generation.在这里默认首先把对像都放到区域的左边.


J2SEHotSpot JVM 4中垃圾回收器都是属于generational collection.

一般说来,新建对象时一般都是在young里面分配内存,old里面储存的是young中经过几次回收依然存活的对象以及一些一开始就在old中分配的大对象.permanent generation里面保存的是类信息和元数据.

younggeneration分为一个Eden区域和两个survivor 区域.对象在Eden区域生成,经过一次GC后存活下来的对象进入survivor,并在此经过更严格的考验,然后进入old .同一时间只有一个survivor区域保存对象,另一个为空.

young区域满了后,就会执行young区域的GC算法.oldpermanent区域满了后,会先执行youngGC.再执行oldpermanentGC,如果old区域对象过多无法执行youngGC,那么在young区域执行oldGC算法(因为内存空间耗费较少),但是CMS回收器的old算法不行,下面会说明原因.

对于多线程的应用.JVM 使用一个Thread-LocalAllocation Buffers ,为每个线程分配一个区域来分配对象,以排除线程竞争.如果此区域满了的话就使用锁.

HotSpot的四种GC 回收器:

串行化回收serial collector:

特点:回收时会暂停应用.

young区域:Eden和某个Survivor区域中的存活的对象复制到另一个Survivor区域(设为TO)(大对象直接放到old区域).如果TO区域满了,则直接复制到old区域.

old区域:使用mark-sweep-compact GC算法,也就是先标记存活对象,然后清除废弃对象,然后把存活对象都移到一块区域,空出一片较大的空闲空间.

适用范围:大部分客户端的应用都可以使用这种回收算法,这也是HotSpot默认的回收算法.在现在的机器(06)上一个64MB的区域的一次完全回收所需的时间不到半秒钟.

并行回收parallel collector:

特点:可以利用多核的CPU.

young区域:同样还是要暂停应用,基本机制和串行化差不多,不过是使用多线程.可以加快效率.

old区域:同串行化.

多核计算机上面可以使用.

并行压缩回收parallel compacting collector:

与并行回收相比,主要是在old区域有个新的算法,同时,按白皮书的说法,这种回收最终会替代并行回收.

young区域:同并行回收.

old区域:首先,old分为几个连续的区域.然后,在每个区域并行的进行检查,标记出alive的对象(先标记出可以直接引用的对象,然后是所有的).然后开始对这些区域进行检查,得出密集程度(左边的区域肯定比右边的密集),从某个密集程度不很高的区域开始,并行的对右边区域进行压缩.

适应范围:对于多核,且对pause time有要求的环境下,使用并行压缩回收比并行回收要好.但是对于高共享率的服务器(也就说一台服务器运行多个应用),由于old区域的collection较慢,又是多线程,所以一个应用的GC会对其他应用造成影响.对应的解决方法:可以配置减少并行时的线程数目.

并行标记清除回收Concurrent Mark Sweep collector:

young区域:同并行回收.

old区域:分为几个步骤.

Initialmark:在需要执行GC,先暂停应用,然后把所有直接引用到的对象进行标记.

Concurrentmark:然后继续应用,并同时对已标记对象进行检查,得到所有存活的对象.

remark:再次暂停应用,Concurrent mark持续期间应用程序修改了的对象进行检查(新增的,废弃的),并标记存活对象.这个阶段持续时间较长,因此会使用多线程.在阶段结束后,所有的存活对象都被标记了,未标记的对象就是垃圾对象了.

sweep:停止暂停应用程序,然后把所有垃圾对象的空间释放.

与其他算法的不同点:

第一:不执行压缩.不过会通过计算将来可能的内存需求而合并/分割某些内存块.

第二:不是old区域要满了才执行GC,而是在空间小于一定程度时开始.

第三:由于没执行压缩,因此会产生碎片.


另外,CMS还可以使用增量运行方式,就是在Concurrentmark阶段只执行一部分工作,然后把资源还给应用程序.回收器的工作会分为几个部分并安排在两次young区域的回收空闲阶段完成.这种模式一般用在对暂停时间有要求,同时处理器数目不多的情况下(单核或双核).

总体说来,与并行回收相比,CMS降低了old GC的暂停时间(有时候效果很显著),轻微的加长了young GC的时间(因为对象从young区域转到old区域时间会加长:没执行压缩,因此要先找到合适的区域),降低了整个系统的一些执行效率,以及很大的加强了对于内存空间的需求.

适用范围:对暂停时间有要求,服务器能够分配一些资源给GC线程.一般说来,适用于应用相对而言有一些比较大的old generation,并且是多核处理器的服务器.比如说web server(这里特别指明web server了)





分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics