JVM介绍
收集器
常见收集器如:Serial收集器、Serial Old收集器、ParNew收集器、Parallel Scavenge收集器、Parallel Old收集器、CMS收集器、G1收集器
Serial收集器
Serial收集器是最基本的,发展历史最悠久的收集器。在JDK1.3之前是虚拟机新生代收集的唯一选择。是一种单线程收集器,只会使用一个CPU或者一条收集线程去完成垃圾收集工作,在进行垃圾收集的时候需要暂停其他线程
- 优点:简单高效,很高的单线程收集效率
- 缺点:收集过程需要暂停所有线程
- 算法:复制算法
- 使用范围:新生代
- 应用:client模式下的默认新生代收集器
Serial Old收集器
Serial Old收集器是Serial收集器的老年代版本,是一个单线程收集器,不同的采用标记-整理算法,运行过程和Serial收集器一样。
ParNew
可以理解为Serial收集器的多线程版本
- 优点:在多CPU时,比Serial效率高
- 缺点:收集过程暂停所有应用程序线程,单CPU时比Serial效率差
- 算法:复制算法
- 使用范围:新生代
- 应用:运行在server模式下的虚拟机中首选的新生代收集器
Parallel Scavenge
Parallel Scavenge收集器是一个新生代收集器。使用复制算法,并行的多线程收集器。与ParNew不同的是更关注系统的吞吐量
吞吐量=运行用户代码的时间/(运行用户代码时间+垃圾收集时间)
如虚拟机总共运行了100分钟,垃圾收集用了1分钟吞吐量=(100-1)/100=99%
若吞吐量越大,意味着垃圾收集的时间越短,则用户代码可以充分利用CPU资源,尽快完成程序的运算任务。
-XX:MaxGCPauseMillis控制最大的垃圾收集停顿时间
-XX:GCRatio直接设置吞吐量的大小
Parallel Old
Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用多线程标记-整理算法进行垃圾回收,更加关注系统的吞吐量
CMS收集器
Concurrent Mark Sweep收集器是一种以获取最短回收停顿时间为目标的收集器。CMS采用 标记-清理 的算法,标记出垃圾对象,清除垃圾对象。算法是基于老年代执行的,因为新生代产生无法接受该算法产生的碎片垃圾。可以配合新生代的Serial和ParNew收集器一起使用
- 优点:并发收集,低停顿
- 不足:无法处理浮动垃圾,并发收集会造成内存碎片过多; CPU资源非常敏感,在并发阶段虽然不会导致用户线程停顿,但是会因为占用了一部分CPU资源,如果在CPU资源不足的情况下应用会有明显的卡顿。
采用的是标记-清除算法整个过程分为4步:
- 初始标记阶段:会让线程全部停止,也就是 Stop the World 状态
- 并发标记阶段:对所有的对象进行追踪,这个阶段最耗费时。但这个阶段是和系统并发运行的,所以不会对系统运行造成影响
- 重新标记阶段:由于第二阶段是并发执行的,一边标记垃圾对象,一边创建新对象,老对象会变成垃圾对象。 所以第三阶段也会进入 Stop the World 状态,并且重新标记,标记的是第二阶段中变动过的少数对象,所以运行速度很快
- 并发清理阶段: 这个阶段也是会耗费很多时间,但由于是并发运行的,所以对系统不会造成很大的影响。
G1收集器
G1收集器收集范围是老年代和新生代。不需要结合其他收集器使用。
G1(Garbage-Frist) JDK8推荐使用的 比CMS的停顿时间短。优先回收垃圾价值高的区域,某种程度上解决空间碎片的问题。
- 初始标记(Initial Marking):仅仅只是标记一下GC Roots能直接关联到的对象,并且修改TAMS指针的值,让下一阶段用户线程并发运行时,能正确地在可用的Region中分配新对象。这个阶段需要停顿线程,但耗时很短,而且是借用进行Minor GC的时候同步完成的,所以G1收集器在这个阶段实际并没有额外的停顿。
- 并发标记( Concurrent Marking):从GC Root开始对堆中对象进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,这阶段耗时较长,但可与用户程序并发执行。当对象图扫
描完成以后,并发时有引用变动的对象会产生漏标问题,G1中会使用SATB(snapshot-at-the-beginning)算法来解决,后面会详细介绍。 - 最终标记(Final Marking):对用户线程做一个短暂的暂停,用于处理并发标记阶段仍遗留下来的最后那少量的SATB记录(漏标对象)。 多个线程同时标记
- 筛选回收(Live Data Counting and Evacuation):负责更新Region的统计数据,对各个Region的回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划,可以自由选择任意多个Region构成回收集,然后把决定回收的那一部分Region的存活对象复制到空的Region中,再清理掉整个旧Region的全部空间。这里的操作涉及存活对象的移动,是必须暂停用户线程,由多个收集器线程并行完成的。
什么情况下应该考虑使用G1
参考官方文档:
- 实时数据占用超过一半的堆空间
- 对象分配或者晋升的速度变化大
- 希望消除长时间的GC停顿(超过0.5-1秒)
G1设置参数
控制G1回收垃圾的时间
-XX:MaxGCPauseMillis=200 (默认200ms)
来源:
JVM垃圾收集器知识 (baidu.com)
CMS收集器和G1收集器的区别g1和cms的区别技术无产者的博客-CSDN博客