JVM垃圾收集器简要概括

来源:互联网 发布:淘宝质量问题赔偿标准 编辑:程序博客网 时间:2024/06/08 07:41

1、Serial:


单线程   复制算法   新生代收集器


2、ParNew:


多线程   复制算法   新生代收集器

           -XX:UseParNewGC :强制选择ParNew收集器

           -XX:ParallelGCThreads: 限制收集线程数


3、Parallel Scavenge:


多线程   复制算法   新生代收集器


 与其他收集器主要关注于尽可能的缩短Stop The Word的时间不同,该收集器的目标是达到一个可控制的吞吐量

         -XX:MaxGCPauseMillis:最大垃圾回收暂停时间

 -XX:GCTimeRatio:设置吞吐量大小GCTimeRatio参数的值应当是一个大于0且小于100的整数,也就是垃圾收集时间占总时间的比率,

 当于是吞吐量的倒数。如果把此参数设置为19,那允许的最大GC时间就占总时间的5%(即1/(1+19)),默认值为99,

就是允许最大1%(即1/(1+99))的垃圾收集时间。


  -XX:+UseAdaptiveSizePolicy:这是一个开关参数,当这个参数打开之后,就不需要手工指定新生代的大小(-Xmn)、

Eden与Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象年龄(-XX: PretenureSizeThreshold)等细节参数了,虚拟机会根据当前系统的运行情况收集性能 监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量,这种调节方式称为GC自适应的调节策略

(GC Ergonomics)。


4、Serial Old:Serial的老年代版本


               单线程   标记-整理算法   老年代收集器


5、Parallel Old: Parallel Scavenge的老年代版本

多线程   标记-整理算法   老年代收集器


6、CMS:Concurrent Mark Sweep

多线程   标记-清除算法   老年代收集器

是一种以获取最短回收停顿时间为目标的收集器

该收集器跟前面的其他相比要复杂一些,整个过程分成了四个阶段
1)初始标记(CMS initial mark)
2)并发标记(CMS concurrent mark)
3)重新标记(CMS remark)
4)并发清除(CMS concurrent sweep)
其中,初始标记、重新标记这两个步骤仍然需要“Stop The World”。初始标记仅仅只是标记一下GC Roots能直接关联到的对象,
速度很快,并发标记阶段就是进行GC RootsTracing的过程,
而重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,
这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。
CMS是一款优秀的收集器,它的主要优点在名字上已经体现出来了:并发收集、低停顿,Sun公司的一些官方文档中也称之为并发低停顿收集器(Concurrent Low Pause Collector)。但是CMS还远达不到完美的程度,它有以下3个明显的缺点:
1)CMS收集器对CPU资源非常敏感。
2)CMS收集器无法处理浮动垃圾(Floating Garbage),可能出现“Concurrent Mode Failure”失败而导致另一次Full GC     的产生。
     由于CMS收集器在并发清除的同时用户程序是没有停止的,所以这就会产生一个问题,在收集器收集的同时还会有垃     圾产生,这就叫做“浮动垃圾”。
     因为CMS在清除垃圾的同时用户程序还需要运行,那也就还需要预留有足够的内存空间给用户线程使用,因此CMS     收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,需要预留一部分空间提供并发收集时的程序                运作使用。在JDK 1.5的默认设置下,CMS收集器当老年代使用了68%的空间后就会被激活,这是一个偏保守的设    置,如果在应用中老年代增长不是太快,可以适当调高参数-XX:CMSInitiatingOccupancyFraction的值来提高触发       百分比,以便降低内存回收次数从而获取更好的性能,在JDK 1.6中,CMS收集器的启动阈值已经提升至92%。
3)还有最后一个缺点,在本节开头说过,CMS是一款基于“标记—清除”算法实现的收集器,如果读者对前面这种算法介绍还有印象的话,就可能想到这意味着收集结束时会有大量空间碎片产生。空间碎片过多时,将会给大对象分配带来很大麻烦,往往会出现老年代还有很大空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前触发一次Full GC。为了解决这个问题,CMS收集器提供了一个-XX:+UseCMSCompactAtFullCollection开关参数(默认就是开启的),用于在CMS收集器顶不住要进行FullGC时开启内存碎片的合并整理过程,内存整理的过程是无法并发的,空间碎片问题没有了,但停顿时间不得不变长。虚拟机设计者还提供了另外一个参数
-XX:CMSFullGCsBeforeCompaction,这个参数是用于设置执行多少次不压缩的Full GC后,跟着来一次带压缩的(默认值为0,表示每次进入Full GC时都进行碎片整理)。


7、G1收集器:

G1是一款面向服务端应用的垃圾收集器。G1具备如下特点。

并行与并发:G1能充分利用多CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心)来缩短Stop-The-World停顿的时间,
部分其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍然可以通过并发的方式让Java程序继续执行。

分代收集:与其他收集器一样,分代概念在G1中依然得以保留。虽然G1可以不需要其他收集器配合就能独立管理整个GC堆,
但它能够采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象以获取更好的收集效果。

空间整合:与CMS的“标记—清理”算法不同,G1从整体来看是基于“标记—整理”算法实现的收集器,
从局部(两个Region之间)上来看是基于“复制”算法实现的,
但无论如何,这两种算法都意味着G1运作期间不会产生内存空间碎片,收集后能提供规整的可用内存。这种特性有利于程序长时间运行,
分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。   可预测的停顿:这是G1相对于CMS的另一大优势,降低停顿时间是G1和CMS共同的关注点,但G1除了追求低停顿外,
还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,
消耗在垃圾收集上的时间不得超过N毫秒,这几乎已经是实时Java(RTSJ)的垃圾收集器的特征了。
如果不计算维护Remembered Set的操作,G1收集器的运作大致可划分为以下几个步骤:
1)初始标记(Initial Marking)
2)并发标记(Concurrent Marking)
3)最终标记(Final Marking)
4)筛选回收(Live Data Counting and Evacuation)
对CMS收集器运作过程熟悉的读者,一定已经发现G1的前几个步骤的运作过程和CMS有很多相似之处。
初始标记阶段仅仅只是标记一下GC Roots能直接关联到的对象,并且修改TAMS(Next Top at Mark Start)的值,
让下一阶段用户程序并发运行时,能在正确可用的Region中创建新对象,这阶段需要停顿线程,但耗时很短。
并发标记阶段是从GC Root开始对堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长,但可与用户程序并发执行。
而最终标记阶段则是为了修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录,
虚拟机将这段时间对象变化记录在线程Remembered Set Logs里面,
最终标记阶段需要把Remembered Set Logs的数据合并到Remembered Set中,这阶段需要停顿线程,但是可并行执行。
最后在筛选回收阶段首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划,
从Sun公司透露出来的信息来看,这个阶段其实也可以做到与用户程序一起并发执行,但是因为只回收一部分Region,
时间是用户可控制的,而且停顿用户线程将大幅提高收集效率。    

垃圾收集器参数总结:






本篇文章参考了周志明的《深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)》一书,在此表示感谢


0 0