面试遇到面试官问这部分可以这样回答:
不同的厂商会考虑使用不同的JVM,不同的JVM会使用不同的垃圾收集器,下面我介绍下主流的垃圾收集器有哪些(主流的7种),下面你就可以展开去说明七种垃圾收集器的每一个细节。
(1).截止JDK 1.8,一共有7款不同的垃圾收集器。每一款不同的垃圾收集器都有不同的特点,在具体使用的时候,需要根据具体的情况选用不同的垃圾收集器
(2).不同厂商、不同版本的虚拟机实现差别很大。HotSpot 虚拟机在JDK7/8后所有收集器及组合(连线),如下图:
①. 评估GC的性能指标
①. 吞吐量:运行用户代码的时间占总运行时间的比例
吞吐量 = 运行用户代码时间 /(运行用户代码时间 + 垃圾收集时间)
比如:虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%
吞吐量优先,意味着在单位时间内,STW的时间最短:0.2 + 0.2 = 0.4
- ②. 暂停时间:执行垃圾收集时,程序的工作线程被暂停的时间
暂停时间优先,意味着尽可能让单次STW的时间最短:0.1 + 0.1 + 0.1 + 0.1 + 0.1 = 0.5
③. 内存占用: Java堆区所占的内存大小
④. 垃圾收集开销:吞吐量的补数,垃圾收集所用时间与总运行时间的比例
⑤. 收集频率:相对于应用程序的执行,收集操作发生的频率
(类似于大学洗衣服,天天洗,每次很快洗完;一周洗,洗很久)
(手机频率高,垃圾线程所用时间短,吞吐量低)
⑥. 评估GC的性能指标:吞吐量vs暂停时间
这三者共同构成一个“不可能三角”。三者总体的表现会随着技术进步而越来越好。一款优秀的收集器通常最多同时满足其中的两项。
这三项里,暂停时间的重要性日益凸显。因为随着硬件发展,内存占用 多些越来越能容忍,硬件性能的提升也有助于降低收集器运行时对应用程序的影响,即提高了吞吐量。而内存的扩大,对延迟反而带来负面效果。
简单来说,主要抓住两点:吞吐量、暂停时间
现在JVM调优标准:在最大吞吐量优先的情况下,降低停顿时间
②. 不同的垃圾回收器概述
①. 垃圾收集器发展史
1999年随JDK1.3.1一起来的是串行方式的Serial GC ,它是第一款GC。ParNew垃圾收集器是Serial收集器的多线程版本
2002年2月26日,Parallel GC 和Concurrent Mark Sweep GC跟随JDK1.4.2一起发布
Parallel GC在JDK6之后成为HotSpot默认GC
2012年,在JDK1.7u4版本中,G1可用。-XX:+UseG1GC
2017年,JDK9中G1变成默认的垃圾收集器,以替代CMS
2018年3月,JDK 10中G1垃圾回收器的并行完整垃圾回收,实现并行性来改善最坏情况下的延迟
2018年9月,JDK11发布。引入Epsilon 垃圾回收器,又被称为"No-Op(无操作)"回收器。同时,引入ZGC:可伸缩的低延迟垃圾回收器(Experimental)
2019年3月,JDK12发布。增强G1,自动返回未用堆内存给操作系统。同时,引入
Shenandoah GC:低停顿时间的GC(Experimental)
2019年9月,JDK13发布。增强ZGC,自动返回未用堆内存给操作系统
2020年3月,JDK14发布。删除CMS垃圾回收器。扩展ZGC在macOS和Windows上的应用
②. 7款经典的垃圾收集器
串行回收器:Serial、Serial Old
并行回收器:ParNew、Parallel Scavenge、Parallel Old
并发回收器:CMS、G1
③. 7款经典的垃圾收集器与垃圾分代之间的关系
新生代收集器: Serial GC、ParNew GC、Parallel Scavenge GC
老年代收集器: Serial 0ld GC、 Parallel 0ld GC、 CMS GC
整堆收集器: G1 GC
④. 垃圾收集器的组合关系
个收集器间有连线,表明它们可以搭配使用:Serial/Serial 01d、Serial/CMS、 ParNew/Serial 01d、ParNew/CMS、Parallel Scavenge/Serial 01d、Parallel Scavenge/Parallel 0ld、G1;
其中Serial 0ld作为CMS 出现"Concurrent Mode Failure"失败的后 备预案。
(红色虚线)由于维护和兼容性测试的成本,在JDK 8时将Serial+CMS、ParNew+Serial 01d这两个组合声明为废弃(JEP 173) ,并在JDK 9中完全取消了这些组合的支持(JEP214),即:移除。(绿色虚线)JDK 14中:弃用Parallel Scavenge和Serial0ld GC组合(JEP366 )(青色虚线)JDK 14中:删除CMS垃圾回收器 (JEP 363)
- ⑤. 查看默认的垃圾收集器
- -xx:+PrintCommandLineFlags: 查看命令行相关参数(包含使用的垃圾收集器)
/** * -XX:+PrintCommandLineFlags * -XX:+UseSerialGC:表明新生代使用Serial GC ,同时老年代使用Serial Old GC * -XX:+UseParNewGC:标明新生代使用ParNew GC * -XX:+UseParallelGC:表明新生代使用Parallel GC * -XX:+UseParallelOldGC : 表明老年代使用 Parallel Old GC * 说明:二者可以相互激活 * -XX:+UseConcMarkSweepGC:表明老年代使用CMS GC。同时,年轻代会触发对ParNew 的使用 */ public class GCUseTest { public static void main(String[] args) { ArrayList<byte[]> list = new ArrayList<>(); while(true){ byte[] arr = new byte[100]; list.add(arr); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } } 输出: (-XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4294967296 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC)
使用命令行指令: jinfo 一flag 相关垃圾回收器参数进程ID
( jinfo -flag UseParallelGC 进程id
jinfo -flag UseParallelOldGC 进程id )