jvm【五】垃圾收集器


[toc]

HotSpot JVM收集器

下面有7中收集器,分为两块, 上面为新生代收集器,下面是老年代收集器。如果两个收集器之间存在连线,就说明它们可以搭配使用。如下图:


Serial(串行GC)收集器--新生代--复制算法

Serial收集器是最基本、发展历史最悠久的收集器(JDK1.3之前)是 虚拟机新生代收集的唯一选择。

特点是:

  1. 在它进行垃圾收集的时,必须暂停其他所有的工作线程,直到它收集结束。
  2. 举例:你妈打扫房间,必须把你赶出去,不然一边打扫,一边扔垃圾,永远也收集不完。
  3. 使用场景:依然是虚拟机运行在Client模式下的默认新生代收集器(仅仅是新生代使用的内存,桌面应用基本不会太大,停顿时间控制在几十毫秒)。

ParNew(并发GC)收集器--新生代--复制算法

ParNew收集器其实就是 serial收集器的多线程版本,除了使用 多条线程进行垃圾收集之外,其余行为与Serial收集器一样。

特点是:

  1. 是许多运行在Server模式下的虚拟机中首选的新生代收集器。
  2. 目前只有它可以 与CMS收集器配合工作。
  3. 并发收集器,垃圾收集线程和用户线程同时工作,做到了妈妈扫房间,你一边扔垃圾

Parallel Scavenge(并行回收GC)收集器--新生代--复制算法

Parallel Scavenges收集器是新生代收集器,是复制算法的收集器,有事并行的多线程收集器。

吞吐量 = 运行用户代码时间/(运行用户代码时间+垃圾收集时间)

特点:

  1. CMS是减少用户停顿时间,而这个收集器的目的是 达到一个可控制的吞吐量。
  2. 停顿时间少能提升用户体验, 高吞吐量可以高效率的利用CPU时间,适合后台运算而不需要太多交互的任务。
  3. --XX:MaxGPauseMillis:接收一个>0的毫秒数,收集器尽可能保证内存回收时间不超过这个值,但是这个值设置的过小,那么频率就会快一些, 如果10S/次、每次100ms,编程5S一次,每次70ms则,吞吐量反而下降。
  4. --XX:GCTimeRatio:直接设置吞吐量大小,接收0<x<100的整数, 也就是垃圾收集时间占总时间的比率,如果为19,那么GC时间比为:1/(1+19),默认为99即则垃圾时间为1%。
  5. --XX:+UseAdaptiveSizePolicy,可以根据当前系统的运行情况收集监控信息,以提供最合适的停顿时间或者最大的吞吐量。
  6. 自适应调节策略也是Parallel Scavenge收集器与ParNew收集器的重要区别。

Serial Old(串行GC)收集器--老年代--标记-整理算法

Serial Old是Serial收集器的老年代版本,它同样使用一个单线程执行收集,使用 “标记-整理”算法。主要使用在 Client模式下的虚拟机。


Parallel Old(并发GC)收集器--老年代--标记-整理算法

Parallel Old是Parallel Scavenge收集器的老年代版本,使用 多线程和“标记-整理”算法。 适用场景:**Parallel Scavenge(新生代)+Parallel Old(老年代)可以适用高吞吐量优先的应用。


CMS(并发GC)收集器--老年代--标记-清除

CMS(Concurrent Mark Sweep)收集器是 获取最短停顿时间为目标的收集器。 适用于互联网站或者B/S系统的服务端上

分为四个步骤:

1. 初始标记

暂停其他用户线程,标记一下GC Roots能直接关联到得对象,速度很快。

2. 并发标记

进行GC Roots Tracing的过程。

3. 重新标记

暂停其他用户线程,是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,停顿时间比出事标记长,但远比并发标记时间短。

4. 并发清除

与用户线程一起并发执行。

特点:

并发收集,低停顿。

缺点

  1. CMS对CPU资源分厂敏感。在并发阶段,它虽然不会导致用户线程停顿,但是会因为占用了一部分线程(或者说是CPU资源)导致应用程序变慢,总吞吐量会降低。
  2. 无法处理浮动垃圾,可能出现 ”concurrent mode failure“失败而导致另一次Full GC的产生。由于CMS并发清理阶段,用户线程还在运行着,伴随程序运行自然就还会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在档次收集中处理掉它们,只好留待下一次GC时再清理掉。这一部分垃圾就称为”浮动垃圾“。 在JDK1.5默认设置下,CMS收集器当老年代使用了68%的空间后就会被激活。可用参数,-XX:+UseCMSInitiationOccupancyFraction进行设置出发百分比,JDK1.6中启动阈值提升到了92%。
  3. 由于使用了"标记-清除"算法实现的收集器,会产生大量的空间碎片,会给分配大对象带来麻烦,会出现老年代剩余空间大,但是无法找到足够到大的连续空间来分配当前对象。会出发一次Full GC。-XX:+UseCMSCompactAtFullCollection开关(默认开启),Full Gc带来的问题肯定就是停顿时间变长。

G1收集器--标记-整理

G1(Garbage First)收集器是JDK1.7提供的一个新收集器,G1收集器基于“标记-整理”算法实现,也就是说不会产生内存碎片。还有一个特点之前的收集器进行收集的范围都是整个新生代或老年代,而G1将整个Java堆(包括新生代,老年代)。

特点

  1. 并行与并发:能充分利用多CPU,在缩短Stop-The_World停顿时间,部分其他收集器原本需要停顿Java线程执行的GC动作,G1仍然可以通过并发的方式让Java程序继续执行。
  2. 分代收集:
  3. 空间整合:标记整理算法,不会产生内存空间碎片。
  4. 可预测的停顿:

收集器参数大全

-XX:+<option> 启用选项
-XX:-<option> 不启用选项
-XX:<option>=<number>
-XX:<option>=<string>

参数描述

-XX:+UseSerialGC

Jvm运行在Client模式下的默认值,打开此开关后,使用Serial + Serial Old的收集器组合进行内存回收
-XX:+UseParNewGC打开此开关后,使用ParNew + Serial Old的收集器进行垃圾回收
-XX:+UseConcMarkSweepGC使用ParNew + CMS +  Serial Old的收集器组合进行内存回收,Serial Old作为CMS出现“Concurrent Mode Failure”失败后的后备收集器使用。
-XX:+UseParallelGCJvm运行在Server模式下的默认值,打开此开关后,使用Parallel Scavenge +  Serial Old的收集器组合进行回收
-XX:+UseParallelOldGC使用Parallel Scavenge +  Parallel Old的收集器组合进行回收
-XX:SurvivorRatio新生代中Eden区域与Survivor区域的容量比值,默认为8,代表Eden:Subrvivor = 8:1
-XX:PretenureSizeThreshold直接晋升到老年代对象的大小,设置这个参数后,大于这个参数的对象将直接在老年代分配
-XX:MaxTenuringThreshold晋升到老年代的对象年龄,每次Minor GC之后,年龄就加1,当超过这个参数的值时进入老年代
-XX:UseAdaptiveSizePolicy动态调整java堆中各个区域的大小以及进入老年代的年龄
-XX:+HandlePromotionFailure是否允许新生代收集担保,进行一次minor gc后, 另一块Survivor空间不足时,将直接会在老年代中保留
-XX:ParallelGCThreads设置并行GC进行内存回收的线程数
-XX:GCTimeRatioGC时间占总时间的比列,默认值为99,即允许1%的GC时间,仅在使用Parallel Scavenge 收集器时有效
-XX:MaxGCPauseMillis设置GC的最大停顿时间,在Parallel Scavenge 收集器下有效
-XX:CMSInitiatingOccupancyFraction设置CMS收集器在老年代空间被使用多少后出发垃圾收集,默认值为68%,仅在CMS收集器时有效,-XX:CMSInitiatingOccupancyFraction=70
-XX:+UseCMSCompactAtFullCollection
由于CMS收集器会产生碎片,此参数设置在垃圾收集器后是否需要一次内存碎片整理过程,仅在CMS收集器时有效
-XX:+CMSFullGCBeforeCompaction
设置CMS收集器在进行若干次垃圾收集后再进行一次内存碎片整理过程,通常与UseCMSCompactAtFullCollection参数一起使用
-XX:+UseFastAccessorMethods
原始类型优化
-XX:+DisableExplicitGC
是否关闭手动System.gc
-XX:+CMSParallelRemarkEnabled
降低标记停顿
-XX:LargePageSizeInBytes
内存页的大小不可设置过大,会影响Perm的大小,-XX:LargePageSizeInBytes=128m

Client、Server模式默认GC

 新生代GC方式老年代和持久GC方式

Client

Serial 串行GCSerial Old 串行GC
ServerParallel Scavenge  并行回收GCParallel Old 并行GC

Sun/oracle JDK GC组合方式

 新生代GC方式老年代和持久GC方式

-XX:+UseSerialGC

Serial 串行GCSerial Old 串行GC
-XX:+UseParallelGCParallel Scavenge  并行回收GCSerial Old  并行GC
-XX:+UseConcMarkSweepGCParNew 并行GCCMS 并发GC
当出现“Concurrent Mode Failure”时
采用Serial Old 串行GC
-XX:+UseParNewGCParNew 并行GCSerial Old 串行GC
-XX:+UseParallelOldGCParallel Scavenge  并行回收GCParallel Old 并行GC
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
Serial 串行GCCMS 并发GC 
当出现“Concurrent Mode Failure”时
采用Serial Old 串行GC

摘自:《深入理解Java虚拟机 JVM高级特性与最佳实践》 参考:http://blog.csdn.net/java2000_wl/article/details/8030172

nemotan /
Published under (CC) BY-NC-SA in categories jvm  tagged with jvm