按执行机制划分Java有四种类型的垃圾回收器:
- 串行垃圾回收器(Serial Garbage Collector)
- 并行垃圾回收器(Parallel Garbage Collector)
- 并发标记扫描垃圾回收器(CMS Garbage Collector)
- G1垃圾回收器(G1 Garbage Collector)
每种类型都有自己的优势与劣势,在很大程度上有 所不同并且可以为我们提供完全不同的应用程序性能。重要的是,我们编程的时候可以通过向JVM传递参数选择垃圾回收器类型。每种类型理解每种类型的垃圾回收器并且根据应用程序选择进行正确的选择是非常重要的。
串行垃圾回收器
串行垃圾回收器通过持有应用程序所有的线程进行工作。它为单线程环境设计,只使用一个单独的线程进行垃圾回收,通过冻结所有应用程序线程进行工作,所以可能不适合服务器环境。它最适合的是简单的命令行程序(单CPU、新生代空间较小及对暂停时间要求不是非常高的应用)。是client级别默认的GC方式。
通过JVM参数-XX:+UseSerialGC可以使用串行垃圾回收器。
并行垃圾回收器
并行垃圾回收器也叫做 throughput collector 。它是JVM的默认垃圾回收器。与串行垃圾回收器不同,它使用多线程进行垃圾回收。相似的是,当执行垃圾回收的时候它也会冻结所有的应用程序线程。
适用于多CPU、对暂停时间要求较短的应用上,是server级别默认采用的GC方式。可用-XX:+UseParallelGC来强制指定,用-XX:ParallelGCThreads=4来指定线程数处。
并发标记扫描垃圾回收器
并发标记垃圾回收使用多线程扫描堆内存,标记需要清理的实例并且清理被标记过的实例。并发标记垃圾回收器只会在下面两种情况持有应用程序所有线程。
- 当标记的引用对象在Tenured区域;
- 在进行垃圾回收的时候,堆内存的数据被并发的改变。
相比并行垃圾回收器,并发标记扫描垃圾回收器使用更多的CPU来确保程序的吞吐量。如果我们可以为了更好的程序性能分配更多的CPU,那么并发标记上扫描垃圾回收器是更好的选择相比并发垃圾回收器。
通过JVM参数 XX:+USeParNewGC 打开并发标记扫描垃圾回收器。
以上各种GC机制是需要组合使用的,指定方式由下表所示:
垃圾回收的JVM配置
运行的垃圾回收器类型:
GC的优化配置:
使用JVM GC 参数的例子:
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseSerialGC -jar java-application.jar
Java 8 的新特性:
在使用G1垃圾回收器的时候,通过 JVM参数 -XX:+UseStringDeduplication 。 我们可以通过删除重复的字符串,只保留一个char[]来优化堆内存。这个选择在Java 8 u 20被引入。
我们给出了全部的几种Java垃圾回收器,需要根据应用场景,硬件性能和吞吐量需求来决定使用哪一种。
新生代收集器使用的收集器:Serial、PraNew、Parallel Scavenge。
老年代收集器使用的收集器:Serial Old、Parallel Old、CMS。