本来这一篇应该是和大家分享以下HotSpot的算法实现的,但是有部分内容存在一些疑问,还需进一步研究一下,今天就简单介绍一下几种不同的垃圾收集器。
开始之前有几点需要提前介绍一下。
第一点,书中提到了一个词,“Stop The World”——即当进行垃圾收集的时候,必须暂停其它所有的工作线程。
第二点,Java的HotSpot虚拟机有两种工作模式,Client模式(轻量级)和Server模式(重量级)。
可以通过在cmd中输入命令java -version进行查看。
第三点,这个要注意啦!!!在讨论垃圾收集器的时候,并发和并行的概念。
并发:传统意义上并发是只一个时间段内多个线程或进程同时执行(时间片轮流调度),但是时间点上只有一个在执行。
在这里,指用户线程和垃圾收集线程同时执行,分别在不同的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虚拟机》)
GC日志:这里只要记住日志内容每一项代表的规则就可以了。
举个例子,使用IDEA编写如下代码
以前介绍过如何设置idea的JVM参数,这里直接在debug中进行配置,增加打印详细日志参数-XX:+PrintGCDetails
点击debug运行程序,控制台打印如下内容。下面让我们一次进行分析。
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是没有显示的。
喜欢文章或想一起学习的朋友可以关注我,我将会持续更新,有什么疑问或文中有不当之处请给我留言,真诚地希望能与大家一起交流探讨,学习进步。