✅有一个银行系统,对实时性要求比较高,你会怎么选择垃圾回收器?
典型回答
这个题目中比价关键的一个词是“实时性要求比较高”,**实时性意味着延迟低,延迟低意味着停顿时间短。意味着STW的时间短。**那么就需要选择STW耗时短的垃圾回收器。
但是,这个问题很难回答,因为最主要的就是根据不同的JDK版本,可能选择的结果是不一样的。
我们从高往低了开始说。
| JDK版本 | 垃圾收集器选择 |
|---|---|
| >= JDK 12 | Shenandoah GC 或者 ZGC |
| >= JDK 11 & < JDK 12 | ZGC |
| >=JDK 7 | G1 |
| < JDK 7 | Parallel Scavenge + CMS |
垃圾收集器有几种,首先我们肯定要排除Serial GC和Serial Old这两个串行的垃圾回收器了。然后就在区分为并发垃圾回收器和并行垃圾回收器。
并行回收其实就是Parallel Scavenge,Parallel Old,ParNew等收集器。这种垃圾回收器更加关注的是吞吐量(吞吐量=代码运行时间/(代码运行时间+垃圾收集时间),在这个公式里,垃圾收集时间是分母的一部分,但是他并不是全部,他只能一定程度上影响吞吐量,但是这几种垃圾回收器,会综合看吞吐量的指标,并不会极端的优化垃圾收集时间。
而我们说的并发回收比较典型的就是 **CMS、G1等,他们更加关注的垃圾回收的停顿时间。其实主要就是引入了三色标记法。**引入三色标记法之后,就是把STW的时间缩短了,具体原因参考:
所以,如果能选择CMS和G1肯定要比Parallel Scavenge,Parallel Old,ParNew这几个更适合我们的这个场景。而且G1是整堆回收器,而CMS是老年代回收器,所以如果用G1的话,一个就够了,如果用CMS的话,还需要搭配一个年轻代的回收器,比如Parallel Scavenge。
所以,如果是JDK 1.7之后的版本的话(小于JDK 11),建议直接上G1了,当然,G1堆内存大小有一定要求,一般要求4G起步,8G以上最好。G1可以把STW时长控制在10ms-100ms左右。
如果是JDK版本更新的话,比如JDK 11以后,就可以考虑Shenandoah GC 和 ZGC这两个超低延迟垃圾收集器了,他们适用于超大堆内存。暂停时间通常在10ms以下,适合对响应时间有极高要求的应用。