以下内容自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算法.当old和permanent区域满了后,会先执行young的GC.再执行old和permanent的GC,如果old区域对象过多无法执行young的GC,那么在young区域执行old的GC算法(因为内存空间耗费较少),但是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了)
分享到:
相关推荐
J2SE5.0_CN.chm API中文手册
j2se5.0中文版api第2部分,因为上传权限有限,给大家带来不便,请见谅
JAVA API帮助文档 中文版 CHM版 J2SE5.0
很好用的J2SE 5.0 API,具有索引的功能!!!
J2SE5.0 API.chm,这个是英文的,等会再上传中文的,两个加在一起太大了 只好分开传了。。。
很好的j2se的API
Java (J2SE 5.0) and C# Comparison Java (J2SE 5.0) and C# Comparison
对J2SE 5.0中的一些新特性进行了精辟的讲解。
对于java开发人员来说 没有一个帮助文档是很郁闷的 尤其对于自学的朋友们,今天得到一个中文版的J2SE5.0的API,不敢独自享用,共享出来给大家,分为2个部分part01和part02
真正的j2se api 5.0 中文版帮助,有需要的可以下载.
在Eclipse 3.1中体验J2SE 5.0的新特性
提示:本人已将一次性可完整下载版上传,名称为:J2SE 5.0 API (中文版)方便网友下载! 很好用的J2SE 5.0 API,具有索引的功能!!! 下载前请注意:不过由于本人等级太低所以只能分3部分上传,劳烦您下载全部3部分...
提示:本人已将一次性可完整下载版上传,名称为:J2SE 5.0 API (中文版)方便网友下载! 很好用的J2SE 5.0 API,具有索引的功能!!! 下载前请注意:不过由于本人等级太低所以只能分3部分上传,劳烦您下载全部3部分...
提示:本人已将一次性可完整下载版上传,名称为:J2SE 5.0 API (中文版)方便网友下载! 很好用的J2SE 5.0 API,具有索引的功能!!! 下载前请注意:不过由于本人等级太低所以只能分3部分上传,劳烦您下载全部3部分...
J2SE 5.0- Java安全及网络计算的最新技术
Java API帮助文档 J2SE5.0 网页版
2022年J2SE5.0新特性之使用代理服务器Java教程.docx
由韩国出版的J2SE 5.0版的JAVA 2教材源代码
一份我觉得不错的中文J2SE API文档,拿来给大家一起分享
使用如JCreater这类的java简易编程软件,可以利用html格式的api帮助文档实现自动提示功能,不会再产生拼写错误问题! 用法(以JCreater):安装完成后,在提示信息中填入html格式api所在的目录即可。