深入理解JAVA虚拟机学习笔记6——七种垃圾收集器介绍和对比

时间:2023-01-02 09:05:20

本来这一篇应该是和大家分享以下HotSpot的算法实现的,但是有部分内容存在一些疑问,还需进一步研究一下,今天就简单介绍一下几种不同的垃圾收集器。

开始之前有几点需要提前介绍一下。

第一点,书中提到了一个词,“Stop The World”——即当进行垃圾收集的时候,必须暂停其它所有的工作线程。

第二点,Java的HotSpot虚拟机有两种工作模式,Client模式(轻量级)和Server模式(重量级)。

可以通过在cmd中输入命令java -version进行查看。

深入理解JAVA虚拟机学习笔记6——七种垃圾收集器介绍和对比

第三点,这个要注意啦!!!在讨论垃圾收集器的时候,并发和并行的概念。

并发:传统意义上并发是只一个时间段内多个线程或进程同时执行(时间片轮流调度),但是时间点上只有一个在执行。

在这里,指用户线程和垃圾收集线程同时执行,分别在不同的CPU中。

并行:传统意义上并行是不光一个时间段内多个线程或进程同时执行,时间点上也有多个线程或进程在执行(多核CPU)。

在这里,指的是多条垃圾收集线程并行工作,但用户线程处于暂停状态。

知道了这几个概念之后,下面简单介绍一下这七种垃圾收集器。

1 Serial收集器:最基本,发展历史最久远的收集器。

采用单线程的工作方式,会“Stop The World”,适用于Client模式下虚拟机。

优点:和其它单线程的相比,不存在并发,没有线程切换的开销,简单而高效。

2 ParNew收集器:Serial的多线程版本,使用多线程并行进行垃圾收集,并且是并发的,不存在“Stop The World”;适用于Client模式下虚拟机。

3 Parallel Scavenge收集器:也是并行多线程的,与其它的收集器的不用之处在于,Parallel Scavenge收集器关注的是控制吞吐量。可以通过调整参数,控制停顿时间或最大的吞吐量(自适应调节策略)。

吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)

提高吞吐量可以提高CPU的利用率,适合在后台运算而不需要太多交互的任务(什么鬼)?

4 Serial Old收集器:Serial收集器的老年代版本,也是单线程的。

5 Parallel Old收集器:Parallel Scavenge收集器的老年代版本。

6 CMS(Concurrent Mark-Sweep)收集器:为了满足B/S项目响应速度的要求,以获取最短回收停顿时间为目标;可并发收集但是仍然会出现“Stop The World”。

7 G1收集器:当前收集器技术发展最前沿的技术之一;面向服务端应用;

特点:并行+并发;分代收集;空间整合;可预测的停顿;

具体的详情可以对照下表。

深入理解JAVA虚拟机学习笔记6——七种垃圾收集器介绍和对比

另附各收集器之间的组合使用图(图片参照《深入理解JAVA虚拟机》)

深入理解JAVA虚拟机学习笔记6——七种垃圾收集器介绍和对比

GC日志:这里只要记住日志内容每一项代表的规则就可以了。

举个例子,使用IDEA编写如下代码

深入理解JAVA虚拟机学习笔记6——七种垃圾收集器介绍和对比

以前介绍过如何设置idea的JVM参数,这里直接在debug中进行配置,增加打印详细日志参数-XX:+PrintGCDetails

深入理解JAVA虚拟机学习笔记6——七种垃圾收集器介绍和对比

点击debug运行程序,控制台打印如下内容。下面让我们一次进行分析。

深入理解JAVA虚拟机学习笔记6——七种垃圾收集器介绍和对比

1. GC日志开头的“[GC”和“[Full GC”说明了这次垃圾收集的停顿类型,如果有”Full”,说明这次GC发生了”Stop-The-World”;

2. 紧跟着括号内的“System.gc()”表示本次回收的触发方式;

3. 接下来的“[PSYoungGen”,“[ParOldGen”,“[Metaspace”表示GC发生的区域;

4. 方括号里面的“6856K->0K(76288K)”,“8K->6717K(175104K)”等表示的是“GC前该内存区域已使用的容量->GC后该内存区域已使用的容量(该内存区域总容量)”;

5. 方括号外面的“6864K->6717K(251392K)”表示“GC前Java堆已使用容量->GC后Java堆已使用容量(Java堆总容量)”;

6. 再往后的“0.0054064 secs”表示的是内存区域GC所占用的时间,单位是秒;

7. 最后面的“[Times: user=0.06 sys=0.00, real=0.01 secs]”是更具体的时间,分别代表用户态消耗的CPU时间,内核态消耗的CPU时间,操作从开始到结束所用的时钟时间;

8. 书中介绍开头时候还会有如“33.125:”样式的GC发生时间,记录的是从Java虚拟机启动以来经过的秒数,笔者使用的JDK8是没有显示的。

喜欢文章或想一起学习的朋友可以关注我,我将会持续更新,有什么疑问或文中有不当之处请给我留言,真诚地希望能与大家一起交流探讨,学习进步。