垃圾收集器分为新生代收集器、老年代收集器,其中新生代收集器包括:Serial、ParNew、Parallel Scavenge,老年代收集器包括:CMS、Serial Old(MSC)、Parallel Old,另外同时包含新生代和老年代的G1收集器。
Serial可以与CMS、Serial Old搭配使用,ParNew可以与CMS、Serial Old搭配使用,Parallel Scavenge可以与Serial Old、Parallel Old搭配使用。
1. Serial收集器
新生代收集器,工作过程会使用一个处理器或一条收集线程,收集垃圾过程中必须暂停所有用户线程,直到收集结束。
该收集器简单而高效,对于内存资源受限的环境,额外内存消耗最小,Serial收集器对于运行在客户端模式下的虚拟机是一个很好的选择。
2. ParNew收集器
Serial收集器的多线程并行版本,是在服务器端模式下的垃圾收集器的选择,在JDK7前是系统首选的新生代收集器。
3. Prallel Scavenge收集器
并行收集的多线程收集器,其目标是达到一个可控制的吞吐量。吞吐量是指用于用户代码的时间和处理器总消耗时间的比值。
吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 运行垃圾收集时间)
控制吞吐量参数:
-XX:MaxGCPauseMillis //控制最大垃圾收集停顿时间
-XX:GCTimeRatio //直接设置吞吐量大小
4. Serial Old收集器
是Serial收集器的老年代版本,是一个单线程的收集器,使用标记-整理算法。
5. Parallel Old收集器
老年代收集器,是Parallel Scavenge的老年代版本,支持多线程并发收集,基于标记-整理算法实现。
6. CMS收集器
老年代收集器,以获取最短回收停顿时间为目标,收集过程分为初始标记、并发标记、重新标记、并发清除。耗时最长的并发标记和并发清除阶段中,垃圾收集器线程都可以与用户线程一起工作。
其优异性能主要表现在并发收集、低停顿,另外它也存在缺点,包括:
- 对处理器资源的占用会导致吞吐量降低,
- CMS无法处理“浮动垃圾”,有可能出现“Concurrent Mode Failure”,失败进而导致另一次完全“Stop The World”的FULL GC的产生。
- 因采用标记-清除算法,会有大量空间碎片生成。
5. G1收集器
收集新生代和老年代的收集器,主要面向服务端应用,是CMS收集器的替代者和继承者,是“停顿时间模型”的收集器。
采用了Mixed GC模式,把连续的JAVA堆划分为多个大小相等的独立区域,每个Region都可以扮演新生代的Eden空间、Survivor空间,或者老年代空间,根据每个Region的垃圾数量多少来判断收益,进行收集垃圾的效益最大化。
Humongous区域:用于存储大对象,超过Region容量一半的对象被判定为大对象,G1的大多数行为把Gumongous Region作为老年代的一部分来看待。
使用Region划分内存空间,以及具有优先级的区域回收方式,保证了G1收集器在有限的时间内尽可能高的收集效率。
待解决问题:
- 在G1收集器上,每个Region都维护有自己的记忆集,记忆集会记录别的Region指向自己的指针,并标记这些指针分别在哪些卡页的范围之内,卡表实现复杂,因此它比其他传统垃圾收集器占用更高的内存。
- 通过使用原始快照算法来保证收集线程与用户线程能互不干扰,通过设计两个名为TAMS的指针,在并发回收时,新分配的对象都必须在这两个指针位置以上,默认这个地址以上的对象是被隐式标记过,不纳入回收范围。
- 通过-XX:MaxGCPauseMillis参数指定停顿时间,该停顿时间只意味着垃圾回收前的期望值,以衰减值为理论基础来实现停顿预测模型,衰减平均值代表“最近的”平均状态。通过这些信息在不超过期望停顿时间的约束下获得最高的收益。
收集器回收的步骤:
- 初始标记
- 并发标记
- 最终标记
- 筛选回收
除了并发标记外,其余阶段要完全暂停用户线程,其目标是在延迟可控的情况下获得尽可能高的吞吐量。
把期望停顿时间设置为一两百毫秒或两三百毫秒会比较合理。
从整体看是基于标记-整理算法实现的,从局部看是基于标记-复制算法实现。
网友评论