到目前为止,还没有一款完美的垃圾收集器,只有适合对应用相关业务场景。
关键因素
在我们选择垃圾收集器的时候,主要考虑以下的几个关键因素:
- 工作负载和内存大小。根据应用程序的需求选择适合的垃圾收集器。比如,对于内存密集型应用,选择内存使用效率高的垃圾收集器;对于计算密集型应用,选择吞吐量高的垃圾收集器。
- 性能和稳定性。考虑垃圾收集器的性能对应用程序的影响。一些垃圾收集器虽然内存使用效率高,但可能牺牲了部分性能或稳定性。
- 停顿时间和吞吐量。如果应用对响应时间有严格的要求,应该选择停顿时间短的并发垃圾收集器(如CMS、G1、ZGC或Shenandoah);如果对响应时间要求不高,可以选择考虑吞吐量更高的串行或并行收集器。
- 堆大小和硬件配置。对就资源有限的环境,适合使用串行或并行收集器;对于大内存堆和多核cpu,可以考虑使用G1、ZGC或Shenandoah等适应大规模堆和高端硬件的垃圾收集器。
- JVM版本和支持。考虑JVM的版本和所支持的垃圾收集器。某些先进的垃圾收集器只在较新JVM版本中才可以使用。
- 实际测试和评估。最佳方式是通过实际测试和性能评估来确定最适合的垃圾收集器。在生产环境前,对几种候选者进行基准测试,观察它们对程序的影响。
综上所述,选择垃圾收集器需综合考虑应用的需求、环境因素和技术限制,通过实际测试来做出最适合的选择。
具体规则
在上面有相关因素,下面是具体的一些准则
1、优先调整堆的大小让服务器自己来选择
2、如果内存小于100M,使用串行收集器
3、如果是单核,并且没有停顿时间的要求,串行或JVM自己选择
4、如果允许停顿时间超过1秒,选择并行或者 JVM自己选
5、如果响应时间最重要,并且不能超过1秒,使用并发收集器
6、4G以下用parallel,4-8G可以用parNew+CMS,8G以上可以用G1,几百G以上用ZGC
安全点与安全区域
安全点就是指代码中一些特定的位置,当线程运行到这些位置时它的状态是确定的,这样JVM就可以安全的进行一些操作,比如GC等,所以GC不是想什么时候就马上触发的,是需要等所有线程运行的安全点才能触发
特定的安全点有以下几种
- 方法返回之前
- 调用某个方法之后
- 抛出异常的位置
- 循环的末尾
安全区域是什么?
- Safe Point是对一个正在运行的线程的设定的。
- 当线程处于Sleep或中断状态,它能不能响应JVM的中断请求,再运行到Safe Point上,因此引入了safe point。
- Safe Region是指在一段代码片段中,引用关系不会发生变化。在这区区域内的任意地方开始GC都是安全的。