内容简介:上一篇文章中学习了
上一篇文章中学习了 JVM
的垃圾回收机制,和内存分配和回收策略。不过这都是一些理论知识,这篇文章中会学习一下 HotSpot
虚拟机中的垃圾收集器,这都是垃圾回收理论的具体实现。
垃圾收集器
HotSpot
虚拟机中有多种收集器,不同的收集器特点也不同,各年代使用的收集器也可以根据应用的特点和要求进行组合。
Serial 收集器
Serial
收集器是一个单线程的收集器,它不仅只会使用一个 CPU
或一条收集线程去完成垃圾收集工作,而且在垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。
Serial
收集器是 HotSpot
虚拟机在运行 Client
模式下的默认新生代收集器。在垃圾收集时,年轻代使用“复制”算法,老年代使用“标记-整理”算法。
但它也有优点,与其他收集器的单线程相比,由于没有现成交互的开销,专心做垃圾收集,所以其简单而高效;
可以使用 -XX:UseSerialGC
参数选择使用 Serial
收集器,此时年轻代采用 Serail
,老年代采用 Serial Old
。
ParNew 收集器
ParNew
收集器是 Serial
收集器的多线程版本,除了使用多线程进行垃圾回收外,其他几乎一样。
它是许多运行在 Server
模式下的虚拟机首选的新生代收集器,一个很重要的原因是除了 Serial
收集器外,只有 ParNew
收集器与 CMS
收集器配合工作。垃圾收集时,年轻代使用“复制”算法,老年代使用“标记-整理”算法。
ParNew
收集器默认开启的线程数与 CPU
的数量相同,可以使用 -XX:ParallelGCThreas
参数来限制垃圾收集的线程数。使用 -XX:UseParNewGC
参数来使用 ParNew
收集器。
Parallel Scavenge 收集器
Parallel Scavenge
收集器是新生代收集器,也是使用复制算法的多线程收集器。与其他收集器不同的是,它关注的是达到一个可控制的吞吐量,吞吐量 = 运行代码时间 / (运行代码时间 + 垃圾收集时间)。
Parallel Scanenge
收集器提供了两个参数用于精确控制吞吐量。第一个是控制最大垃圾收停顿时间的 -XX:MaxGCPauseMillis
参数。它允许是一个大于 0
的毫秒数,收集器将尽可能保证内存回收时间不超过设定值。这个参数也不是越小越好,GC 停顿时间缩短是以牺牲吞吐量和新生代空间为代价换取的。
第二个是直接设置吞吐量大小的 -XX:GCTimeRatio
参数。它允许是一个大于 0
且小于 100
的整数,就是垃圾收集时间占总时间的比率。
另外, Parallel Scavenge
收集器拥有自适应调节机制,它不需要手工指定新生代的大小( -Xmn
)、 Eden
与 Survivor
区的比例( -XX:SurvivorRatio
)、晋升老年代对象大小 -XX:PretenureSizeThreshold
等细节参数,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整参数以提供最合适的停顿时间及最大的吞吐量。可使用 -XX:UseAdaptiveSizePolicy
参数来开启。
Serial Old 收集器
Serial Old
是 Serial
收集器的老年代版本,是一个单线程收集器,使用“标记-整理算法”。
Parallel Old 收集器
Parallel Old
是 Parallel Scavenge
收集器的老年代版本,使用多线程和“标记-整理”算法。如果新生代选择了 Parallel Scavenge
收集器,老年代只能选择 Serial Old
收集器。
CMS 收集器
CMS(Concurrent Mark Sweep)
是一种以获取最短停顿时间为目标的收集器,使用“标记-清除”算法。如果应用重视响应速度,希望停顿时间最短,就可以选择 CMS
收集器。
它的运作过程可分为 4
个步骤:
- 初始标记:仅仅标记
GC Roots
能直接关联到的对象,速度很快,需要Stop the world
。 - 并发标记:进行
GC Roots Tracing
过程。 - 重新标记:修正并发标记期间因用户程序运行而导致标记产生变动的对象的标记记录。
- 并发清除。
CMS
的主要优点是并发收集、低停顿。但也有三个缺点:
- 对
CPU
资源非常敏感。并发阶段虽不会导致用户线程停顿,但会因为占用资源而导致程序变慢,总吞吐量降低。 - 无法处理浮动垃圾,也就是在标记过程后,清除阶段产生但当次收集中不能处理的垃圾,可能出现
Concurrent Mode Failure
失败而导致另一次Full FC
的产生。 -
CMS
基于标记-清除算法,收集结束时会产生大量空间碎片。碎片过多时,无法找到足够的连续空间来分配大对象,不得不提前出发一次Full GC
。
可以使用 -XX:UseConcMarkSweepGC
参数来选择 CMS
收集器。
G1 收集器
G1(Garbage-First)
是一款面向服务端应用的垃圾收集器。它的特点如下:
- 并行与并发:充分利用多
CPU
、多核环境,使用多个CPU
来缩短停顿的时间,部分需要其他收集器原本需要停顿Java
线程执行的GC
动作,G1
收集器可通过并发的方式让Java
程序继续执行。 - 分代收集:
G1
收集器能独立管理整个GC
堆,并且能采用不同的方式处理不同时期的对象。 - 空间整合:
G1
收集器从整体来看,基于“标记-整理”算法实现;从局部来看,基于“复制”算法实现。 - 可预测的停顿:
G1
能明确指定垃圾收集的限制时间。
使用 G1
收集器时,将 Java
堆划分为多个大小相等的区域 Region
。 G1
跟踪各个 Region
的回收价值和成本(回收获得空间及回收时间),后台会维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的 Region
。它通过使用 Remembered Set
来避免全堆扫描。
G1
收集器的运行步骤可分为:
- 初始标记:仅仅标记一下
GC Roots
直接能关联到的对象,需要停顿,但耗时很短。 - 并发标记:从
GC Roots
开始对堆中对象进行可达性分析,找出存活的对象,耗时较长,但可并发执行。 - 最终标记:修正并发标记期间因用户程序运行而导致标记产生变动的对象的标记记录。
- 筛选回收:对各个
Region
的回收价值和成本进行排序,根据指定的GC
停顿时间制定回收计划。
常用收集器组合
HotSpot
虚拟机中包含了七种垃圾收集器,如下图:
它们的组合说明如下:
新生代收集器 | 年老代收集器 | 说明 |
---|---|---|
Serial | Serial Old | 都是单线程,GC 时会暂停所有应用线程。 使用 -XX:+UseSerialGC 选项来开启 |
Serial | CMS + Serial Old | CMS 是并发 GC,不需要暂停所有应用线程。 当 CMS 进行 GC 失败时,会自动使用 Serial Old 策略进行 GC 使用 -XX:+UseConcMarkSweepGC 选项来开启 |
ParNew | CMS | ParNew 是 Serial 的并行版本,可以指定 GC 线程数 默认 GC 线程数为 CPU 的数量 |
ParNew | Serial Old | 使用 -XX:+UseParNewGC 选项来开启 |
Parallel Scavenge | Serial Old | Parallel Scavenge 策略关注吞吐量,适用于后台持久运行的应用程序 使用 -XX:+UseParallelGC 选项来开启 |
Parallel Scavenge | Parallel Old | Parallel Old 是 Serial Old 的并行版本 使用 -XX:+UseParallelOldGC 选项来开启 |
G1GC | G1GC | -XX:+UseG1GC #开启 -XX:MaxGCPauseMillis #暂停时间目标 |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 【1】JavaScript 基础深入——数据类型深入理解与总结
- 深入理解java虚拟机(1) -- 理解HotSpot内存区域
- 深入理解 HTTPS
- 深入理解 HTTPS
- 深入理解 SecurityConfigurer
- 深入理解 HTTP 协议
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Art of UNIX Programming
Eric S. Raymond / Addison-Wesley / 2003-10-3 / USD 54.99
Writing better software: 30 years of UNIX development wisdom In this book, five years in the making, the author encapsulates three decades of unwritten, hard-won software engineering wisdom. Raymond b......一起来看看 《The Art of UNIX Programming》 这本书的介绍吧!