title: JVM学习笔记——垃圾收集器
date: 2018/9/4 17:09:31
description: 最近开始着手JVM的学习,在这里把自己学习过程中的笔记分享出来,希望能帮到一些小伙伴,同时也是对自己的学习的一个梳理。
垃圾收集器
垃圾收集器内容颇多,但算法原理都是基于垃圾收集算法,故这里只简单介绍一下各收集器的特点。
-
HopSpot中的收集器群
两个虚拟机之间的连线表示它们可以搭配使用,反之则不能搭配。
-
Serial收集器
- 使用“标记-整理”算法
- “单线程”收集器,这里的单线程指的是Serial在对某一条线程执行收集工作时,必须暂停其他线程的运行,这就会造成大量的GC停顿出现。
- 优点是简单高效,在Client模式的虚拟机中表现优秀。
-
Serial Old收集器
- Serial的老年代版本,特性基本与Serial一致。
- 在JDK1.5之前可以与Parallel搭配使用,或者作为CMS的后备方案。
-
ParNew收集器
- ParNew就是针对Serial改进的多线程版本。
- 在很多虚拟机中,ParNew却是新生代的首选收集器,因为除了Serial只有它能够与CMS搭配使用。
-
Parallel Scavenge收集器
- 是一个新生代的收集器,使用多线程+复制算法。
- 主要关注吞吐量的收集器
吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)
,提供两个参数用于精确控制吞吐量:- -XX:MaxGCPauseMillis,最大GC停顿时间。允许的值是一个大于0的毫秒数,收集器尽可能保证收集时间不超过该值。注意,停顿时间缩短需要牺牲吞吐量和空间,更小的停顿时间可能会导致更频繁的GC。
- -XX:GCTimeRatio,GC时间占总时间比率。是一个0-100之间的整数,等于吞吐量的倒数。
-
Parallel Old收集器
- Parallel Scavenge的老年代版本,使用多线程+标记整理算法。
- 由于Serial Old在服务端上性能不佳,故有了该收集器与Parallel Scavenge进行搭配使用。
-
CMS收集器(Concurrent Mark Sweep)
- 基于标记-清除算法实现,是一款以获取最短GC停顿时间为目标的收集器。它的运作过程分为4步:
- 初始标记
标记GC Roots能关联到的对象。 - 并发标记
由GC Roots发起对象的跟踪,验证是否可达。 - 重新标记
修正并发标记期间变动的一部分对象的标记记录。 - 并发清除
清除标记对象的空间。
- 初始标记
其中只有初始标记与重新标记两个过程需要进行停顿,但是这两个过程仅仅是标记,速度很快,最漫长的清除过程在CMS下可以与用户线程并行处理。
- CMS虽然很强大,但还是有着以下3个缺点:
- 虽然CMS不会导致GC停顿,但并发的代价就是会占用CPU资源,可能会导致用户程序变慢,在核数较低的CPU中该问题会越发明显。
- 由于CMS的清理不会暂停用户线程,可能导致“浮动垃圾”的出现,那就需要留出一部分内存空间对应“浮动垃圾”,所以CMS有一个触发回收的内存比例,在JDK1.6中该值默认为92%。如果预留的内存还是无法满足程序需求,CMS就会启动备用方案(一般是Serial Old)来重新进行收集。
- 由于CMS使用的是标记-清除算法,所以会有大量的内存碎片产生,会导致大对象找不到空间存放而提前触发一次Full GC进行内存整理。
- 基于标记-清除算法实现,是一款以获取最短GC停顿时间为目标的收集器。它的运作过程分为4步:
-
G1收集器
在JDK1.7之后才出现的收集器,G1具备以下四个特点:
- 并行与并发,能利用多线程,多CPU的优势,使得GC与用户线程并行。
- G1能够独自对整个GC堆进行管理,并且留有了分代的特性,可以根据不同的区域采用不同的方式处理。
- 将Java堆划分为多个大小相等的独立区域(Region),在Region上来看是基于复制算法实现的,从整体上看是基于标记-整理算法实现,结合了两种算法的优点。
- 建立了可预测的停顿模型,可以通过
-XX:MaxGCPauseMillis
来设置期望GC时间,G1会尽量在该时间内完成GC。