1、java垃圾回收都有哪些方式
所谓垃圾回收方式,是指JVM提供的几种不同的垃圾回收器,不同的垃圾回收器进行垃圾回收时采用不同的方式。当然,总体原则遵循java垃圾回收机制。
了解java内存模型看这里:java内存模型是什么样的
了解堆内存看这里:java堆内存是什么样的
了解java垃圾回收机制看这里:java垃圾回收机制是什么
每种方式都有自己的优势与劣势。我们编程的时候可以通过向JVM传递参数来选择垃圾回收器。不同的垃圾回收期有大的不同,可以为我们提供完全不同的应用程序性能,所以理解每种垃圾回收器,并且根据不同的应用选择进行正确的选择是非常重要的。
垃圾回收器主要有4种:串行垃圾回收器(Serial Garbage Collector)
、并行垃圾回收器(Parallel Garbage Collector)、并发标记扫描垃圾回收器(CMS Garbage Collector)、G1垃圾回收器(G1 Garbage Collector),具体如下:
串行垃圾回收器
串行垃圾回收器通过持有应用程序所有的线程进行工作。它为单线程环境设计,只使用一个单独的线程进行垃圾回收,通过冻结所有应用程序线程进行工作,所以可能不适合服务器环境。它最适合的是简单的命令行程序。
通过JVM参数-XX:+UseSerialGC可以使用串行垃圾回收器。
并行垃圾回收器
并行垃圾回收器是JVM的默认垃圾回收器。与串行垃圾回收器不同,它使用多线程进行垃圾回收。相似的是,当执行垃圾回收的时候它也会冻结所有的应用程序线程。
并发标记扫描垃圾回收器
并发标记垃圾回收使用多线程扫描堆内存,标记需要清理的实例并且清理被标记过的实例。并发标记垃圾回收器只会在下面两种情况持有应用程序所有线程:
- 当标记的引用对象在老生代;
- 在进行垃圾回收的时候,堆内存的数据被并发的改变。
相比并行垃圾回收器,并发标记扫描垃圾回收器使用更多的CPU来确保程序的吞吐量。如果我们能够为了更好的程序性能分配更多的CPU,那么相比并发垃圾回收器,并发标记扫描垃圾回收器是更好的选择。
通过JVM参数XX:+USeParNewGC打开并发标记扫描垃圾回收器。
G1垃圾回收器
G1垃圾回收器将堆内存分割成不同的区域,并且并发的对其进行进行垃圾回收。G1也可以在回收内存之后对剩余的堆内存空间进行压缩。
G1垃圾回收会优先选择第一块垃圾最多的区域,它适用于堆内存很大的情况。
通过JVM参数–XX:+UseG1GC使用G1垃圾回收器
在Java 8中,G1可以通过JVM参数-XX:+UseStringDeduplication删除重复的字符串,只保留一个char[]来优化堆内存。
2、如何选择不同的垃圾回收器
我们需要根据应用场景、硬件性能和吞吐量需求来决定使用哪一种垃圾回收器,通过JVM参数的配置来选择垃圾回收器:
-XX:+UseSerialGC:串行垃圾回收器
-XX:+UseParallelGC:并行垃圾回收器
-XX:+UseConcMarkSweepGC:并发标记扫描垃圾回收器
-XX:ParallelCMSThreads:并发标记扫描垃圾回收器 =为使用的线程数量
-XX:+UseG1GC:G1垃圾回收器
其他内存常见配置:
-Xms:初始化堆内存大小
-Xmx:堆内存最大值
-Xmn:新生代大小
-XX:PermSize:初始化永久代大小
-XX:MaxPermSize:永久代最大容量
配置JVM GC参数的实例:
java -Xmx1024m -Xms512m -Xmn256m -XX:PermSize=64m -XX:MaxPermSize=128m -XX:+UseSerialGC -jar java-application.jar
上述配置的含义是:
堆内存512-1024M,新生代256M,永久代64-128M,采用串行垃圾回收器执行java-application.jar。