之前的讨论都是关于串行收集器的。Java HotSpot VM包括3种不同类型的收集器,不同类型收集器的特性存在明显差别。
串行收集器(Serial Collector)
串行收集器使用一个线程来执行所有的垃圾收集操作,因为不存在线程之间的通信开销,串行收集器性能相对高效。
串行收集器最适合于硬件或平台为单处理器的情况,因为它不能利用多处理器的优势,尽管它对于在多处理器上运行的小数据集(最多100 MB)的应用程序很有用。在某些硬件和操作系统配置上,JVM默认选择串行收集器,也可以通过选项-XX:+UseSerialGC显式启用。
并行收集器(Parallel Collector)
并行收集器也称为吞吐量收集器,它与串行收集器相似。串行收集器和并行收集器的主要区别是并行收集器有多个线程用于加速垃圾收集。
在多处理器或多线程硬件上运行,且应用程序具有大中型数据集时,可以考虑并行收集器。增加-XX:+UseParallelGC选项即可。
并行收集器主要并行执行垃圾收集过程中内存压缩(Compaction)的部分。如果没有并行压缩,垃圾收集将使用单个线程执行,这将极大地限制可伸缩性。如果指定了选项-XX:+UseParallelGC,则默认情况下启用并行压缩。可以使用-XX:-UseParallelOldGC选项禁用。
并发收集器(Concurrent Collector)
并发标记清除(CMS)和垃圾优先(G1)收集器是主要的两种并发收集器。并发收集器通常会对应用程序并发地执行一些代价较高的操作:
1.G1 GC:主要用于java server模式下的垃圾收集,适用于具有大量内存的多处理器程序,它能在实现垃圾收集暂停时间的目标上,尽可能地实现吞吐量目标。
2.CMS GC:CMS适用于需要更短的垃圾收集暂停时间的应用程序,并且CMS在进行垃圾收集的过程中,应用程序依然能利用剩余的处理器资源继续运行。
使用-XX:+UseConcMarkSweepGC命令
可以启用CMS收集器(注:java从JDK 9开始弃用CMS收集器)
Z收集器
Z垃圾收集器(Z GC)是一种可伸缩的低延迟垃圾收集器。Z GC可以在并发地执行所有代价较高的操作时不仪器应用程序线程执行的停止。
ZGC适用于需要低延迟(暂停时间小于10毫秒)和/或使用非常大堆内存(数TB)的应用程序。通过使用-XX:+UseZGC选项启用。
注:Z GC仅作为实验特性加入JDK 11
选择收集器的建议
首先让VM为运行的应用程序自动选择收集器,除非应用程序有特别严格的暂停时间要求。
首先可以通过调整堆大小来优化程序性能。如果性能依然不达标,可以参考下列原则来选择合适的收集器:
1.如果应用程序的数据集很小(最多100 MB),推荐使用-XX:+UseSerialGC选项启用串行收集器。
2.如果应用程序在单处理器上运行,并且没有暂停时间要求,推荐使用-XX:+UseSerialGC选项启用串行收集器。
3.如果应用程序吞吐量优先,并且没有暂停时间要求,或者可以接受1秒或更长时间的暂停,那么让VM自动选择收集器或使用使用-XX:+UseParallelGC选择并行收集器。
4.如果响应时间比总体吞吐量优先级更高,并且垃圾收集暂停时间必须保持在1秒以下,那么选择并发收集器,使用-XX:+UseG1GC或-XX:+UseConcMarkSweepGC。
5.如果对相应时间的要求非常高,并且程序占用的堆空间非常大,那么考虑使用-XX:UseZGC完全并发执行垃圾收集。
上述5点主要是选择收集器的初步建议,因为性能还取决于堆的大小、应用程序维护的活动数据量以及可用的处理器资源。
如果默认的收集器没有达到预期的性能,首先尝试调整堆和代的大小,如果性能依然不达标,再考虑使用不同的收集器:并发收集器缩短程序暂停时间,并行收集器提高多处理器平台上的总吞吐量。