深入理解Java虚拟机读书笔记六

时间:2022-12-27 17:04:44

3.4.垃圾收集器

HotSpot JVM 1.6 的垃圾收集器

深入理解Java虚拟机读书笔记六

3.4.1 .Serial收集器

    这个收集器是一个单线程的收集器,说明它只会使用一个 CPU 或一条收集线程去完成垃城收

集工作,更重要的是在它进行垃圾收集时,必须暂停其他所有的工作线程 (Sun 将这件事情称为 "Stop Thc World“直到收集结束。

    它依然是虚拟机运行在 Client 模式下的默认新生代收集器.

优势:简单而高效〈与其他收集器的单线程比),对于限定单个 CPU 的环境来说. Serial 收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率.

    用单线程处理所有垃圾回收工作,因为无需多线程交互,所以效率比较高。但是,也无法使用多处理器的优势,所以此收集器适合单处理器机器

单线程收集器。在目前多核服务器端运行的情况下,效率比较低。比较适合堆内存小的情况下使用。

深入理解Java虚拟机读书笔记六

3.4.2.ParNew收集器

    ParNew收集器其实就是 Serial收靠器的多线程版本。

深入理解Java虚拟机读书笔记六

    它运行在 Server 模式下的虚拟机中首选的新生代收集器,除了 Serial 收集器外,目前只有它能与 CMS 收集器配合工作。

    口并行 ( Parallel) :指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。

    口并发 ( Con curre nt ) :指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行,用户程序继续运行, 而垃圾收集程序运行于另一个CPU上。

3.4.3.Parallel Scavenge收集器

    Parallel Scavenge收集器也是一个新生代收集器,它也是使用复制算法的收集器,也是并行的多线程收集器,经常被称为“吞吐量优先”收集器 。

    CMS 等收集器的关注点尽可能地缩短垃圾收集时用户线程的停顿时间,而Parallel Scavenge 收集器的目标则是达到一个可控制的吞吐量 (Throughput ) 

    吞吐量:CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)

    停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户的体验。

    高吞吐量则可以最高效率地利用CPU时间,尽快地完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。

    -XX:MaxGCPauseMillis最大垃圾收集停顿时间,值是一个大于0的毫秒数,尽力保证内存回收花费的时间不超过设定值。GC停顿时间缩短是以牺牲吞吐量和新生代空间来换取的。

    比如:系统把新生代调小,收集 300MB 新生代肯定比收集 500MB快,垃圾收集发生更频繁,原来10秒收集一次、每次停顿100毫秒,现在变成秒收集一次、每次停顿70毫秒。在100秒里,原来吞吐量是99%,现在变为98.4%。停顿时间在下降,但吞吐量也下降了。

    -XX:GCTimeRatio吞吐量大小,一个大于0小于100的整数,垃圾手机时间占总时间的比率,相当于是吞吐量的倒数。参数设置为19,那允许的最大 GC 时间就占总时间的 5% ( 即 1 /( 1 + 1 9),默认值为 99

    -XX:+ UseAdaptiveSizePolicy一个开关参数,参数打开后,不需要要手工指定新生代的大小 ( -Xmn ) Eden与 Survivor 区的比例(-XX:SurvivorRatio)等,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或最大的吞吐量,这种调节方式称为GC自适应的调节策略 (GC ErgonomÎcs)

3.4.4.Serial Old收集器

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

在 Server 模式下:

    1.JDK 1 .5 及之前的版本中与Parallel Scavenge收集器搭配使用。

    2.作为 CMS 收集器的后备预案,在并发收集发生 Conc urrenl Mode Failure 的时候使用。

深入理解Java虚拟机读书笔记六

3.4.5.Parallel Old收集器

    Parallel OldParallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。在 JDK 1. 6 中才开始提供的。

深入理解Java虚拟机读书笔记六

3.4.6.CMS收集器

    CMS (Concurrent Mark Sweep ) 收集器是一种以获取最短回收停顿时间为目标的收集器。符合在互联网站或 B/S或系统的服务端上,停顿时间最短,以给用户带来较好的响应速度和体验。

运作过程4个包括:

    1.初始标记 (CMS initial mark ) 

    2.并发标记(CMS concurrent mark ) 

    3.重新标记 (CMS remark ) 

    4.并发清除(CMS concurrent sweep ) 

深入理解Java虚拟机读书笔记六

    初始标记、重新标记这两个步骤仍然需要 “Stop The World”。初始标记只标记一下 GC Roots 直接关联到的对章,速度很快,并发标记阶段就是进行 GCRoots Tracing的过程,而重新标记阶段则是为修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对像的标记记录, 这个阶段的停顿时间一般会比初始标记阶段稍长-些,但远比并发标记的时间短。

由于整个过程中耗时最长的并发标记和并发消除过程中,收集器线程都可以与用户线程一起工作,所以总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。 

优点:并发收集、低停顿。并发低停顿收集器 (Concurrent Low Pause Collector ) 

缺点:

    1.CMS收集器对CPU资源非常敏感。CMS 默认启动的回收线程数是 (CPU 数量 +3) / 4 "增量式并发收集器" (lncremental Concurrent Mark  Sweep /i-CMS )CMS收集器变种。在并发标记和并发清理的时候让GC线程、用户线程交替运行,尽量减少GC线程的独占资源的时候,这样整个垃圾收集的过程会更长,但对用户程序的影响就显得少一些,速度下降也就没有那么明显,当前版本“deprecated”即不再提倡用户使用。

    2.CMS收集器无法处理浮动垃圾 ( Floating Garbage) ,可能出现 "Concurrent Mode Failure"失败而导致另一次Full GC 的产生。在默认设置下,CMS收集器在老年代使用丁68% 的空间后就会被激活,这是一个偏保守的设置,如果在应用中老年代增长不是太快。可以适当调整参数-XX:CMS lnitialingOccupancyFraction 的值提高触发百分比, 以便降低内存回收次数以获取更好的性能。CMS运行期间预留的内存无法满足程序需要,就会出现一次 "Concurrcnt Mode Failure" 失败,虚拟机将启动后备预案,临时启用SerialOld 收集器来重新进行老年代的垃圾收集,这样停顿时间就很长。这个参数设置太高,容易导致大量 "Concurrcnl Mode Failure" 失败,性能降低。

    3.CMS 是一般基于"标记-清除"算法实现的收集器。收集结束时生产生大量空间碎片,空间碎片过多时,出现老年代还有很大的空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前触发一次Full GC.-X X:+UseCMSCompactAtFullCollection开关参数用于在享受完Full GC服务之后额外免费附送一个碎片整理过程,内存整理的过程是无法是并发的。空间碎片问题没有了,但停顿时间不得不变长了。-XX: CMSFullGCsBe foreCompaclion用于设置在执行多少次不压缩的Full GC后,跟着来一次带压缩的。

3.4.7.G1收集器

    G1(Garbage First )收集器改进:

    一是G1收集器是基于"标记一整理"算法实现的收集器,不去产生空间碎片。

    二是它可以非常精确地控制停顿,既能让使用者明确指定在一个长度为 毫秒的时间片段内,消耗在垃圾收集上的时间不得超过 毫秒。

G1收集器器可以实现在基本不牺牲吞吐量的前提下完成低停顿的内存回收,这是由它能够极力地避免全区域的垃圾收集。G1将整个Java堆 包括新生代、老年代划分为多个大小固定的独立区域(Region)时,并且跟踪过些区域里面的垃圾堆积程度,在后台维护一个优先列表,每次根据允许的收集时间,优先回收垃极最多的区域。

区域划分及有优先级的区域回收,保证了G1收集器在有限的时间内可以获得最高的收集效率。

3.4.8.垃圾收集器参数总结

    说明:

    -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:+UseParallelGC

Jvm运行在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:GCTimeRatio

GC时间占总时间的比列,默认值为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