在JDK 8中,默认的垃圾回收器是Parallel GC(也称为吞吐量优先垃圾回收器,-XX:+UseParallelGC
)。
堆内存大小
-Xms
和-Xmx
:通常建议将-Xms
(初始堆大小)和-Xmx
(最大堆大小)设置为相同的值,以避免在应用运行过程中动态调整堆大小带来的性能开销。- 优化建议:假设应用在2GB内存的限制内运行良好,可以将这两个参数都设置为2GB,即
-Xms2048m -Xmx2048m
。如果应用对内存需求更大,则可以适当增加这两个值。
新生代内存
-XX:NewSize
和-XX:MaxNewSize
:新生代的大小应根据应用的对象分配和垃圾回收频率来调节。一般情况下,新的对象大多在新生代分配,因此,如果应用创建大量短生命周期对象,增大新生代内存可以减少Minor GC(小垃圾回收)的频率。- 优化建议:将新生代大小设置为堆内存的1/3至1/4之间是一个常见的选择。比如,如果堆内存为2GB,可以尝试将新生代设置为
-XX:NewSize=512m -XX:MaxNewSize=1024m
,根据应用的实际情况做进一步调整。
垃圾回收器选择
在Java虚拟机(JVM)中,不同的垃圾回收器(GC)适用于不同的应用场景。以下是几个主要垃圾回收器的详细解释,以及选择合适GC的建议和优化建议。
Parallel GC
-
全称:Parallel Garbage Collector
-
特点:
- 年轻代收集:采用并行的“Stop-the-World”垃圾收集,多个线程并行清理年轻代(Young Generation)对象。
- 老年代收集:使用标记-压缩算法(Mark-Compact)对老年代(Old Generation)进行并行垃圾收集。
- 目标:最大化吞吐量,即在最短的时间内处理最多的任务,适合CPU密集型的后台任务。
-
适用场景:
- 大型后台服务、批处理任务、计算密集型应用程序,这些场景对短暂停顿不敏感,但对整体吞吐量要求较高。
-
优化建议:
- 如果应用允许较长时间的暂停,且对吞吐量要求高,可以选择Parallel GC。
- 调整
-Xms
和-Xmx
使堆大小稳定,避免堆大小频繁调整导致的额外开销。
-
推荐参数 Parallel GC 适用于高吞吐量应用。推荐的参数设置:
-
-Xms
-Xmx
:建议设置为相同值,避免堆内存动态调整带来的性能开销
例如:-Xms2048m -Xmx2048m
(根据应用需要调整大小)。 -
-XX:+UseParallelGC
:使用Parallel GC。 -
-XX:ParallelGCThreads
:设置GC线程数,通常设置为CPU核心数的1到2倍。
例如:8核CPU,可以设置为-XX:ParallelGCThreads=8
。 -
-XX:MaxGCPauseMillis
:设置目标最大GC暂停时间(毫秒)。这个值越小,吞吐量可能会下降。
例如:-XX:MaxGCPauseMillis=200
(根据应用需求调整)。 -
-XX:GCTimeRatio
:GC时间与应用时间的比率。默认值是99,表示GC时间占1%,应用时间占99%。
例如:-XX:GCTimeRatio=4
表示GC时间占20%。
-
ParNew GC与CMS GC
ParNew GC
-
全称:ParNew Garbage Collector
-
特点:
- 年轻代收集:与Parallel GC相似,使用并行的垃圾收集,但设计上与CMS GC搭配使用。
- 老年代收集:一般与CMS GC搭配,老年代由CMS GC负责。
- 目标:在降低延迟的同时保持较好的并行垃圾收集性能。
-
适用场景:
- 适用于对延迟要求高的应用,尤其是与CMS GC搭配使用时。
-
优化建议:
- 如果使用CMS GC,可以选择ParNew GC作为年轻代收集器。
- 调整
-XX:NewSize
和-XX:MaxNewSize
的大小,平衡年轻代和老年代的内存使用。
-
参数推荐值
-Xms
和-Xmx
:建议设置为相同值,避免堆内存动态调整带来的性能开销。例如:-Xms2048m -Xmx2048m
(根据应用需要调整大小)。
CMS GC
-
全称:Concurrent Mark-Sweep Garbage Collector
-
特点:
- 老年代收集:CMS GC主要用于老年代垃圾收集,它通过并发标记和清除来减少“Stop-the-World”暂停时间。
- 目标:减少长时间的Full GC停顿,适合对响应时间要求高的应用。
- 缺点:CMS GC可能会出现“concurrent mode failure”,导致频繁的Full GC,还存在“碎片化”问题,内存不能有效利用。
-
适用场景:
- 对延迟敏感的应用,如Web应用、交互式服务、实时系统。
-
优化建议:
- 可以结合
-XX:CMSInitiatingOccupancyFraction
参数,控制在老年代使用到一定比例后触发CMS收集。 - 使用
-XX:+UseCMSCompactAtFullCollection
和-XX:CMSFullGCsBeforeCompaction
参数,减少碎片化问题。
- 可以结合
-
推荐参数 ParNew GC 通常与CMS GC搭配使用,适用于低延迟应用。推荐的参数设置:
-
-XX:+UseParNewGC
:使用ParNew GC进行新生代的并行垃圾收集。 -
-XX:+UseConcMarkSweepGC
:使用CMS GC进行老年代的并发标记-清除垃圾收集。 -
-XX:CMSInitiatingOccupancyFraction
:设置老年代使用率达到多少时开始CMS垃圾收集,避免老年代被过度占用。
例如:-XX:CMSInitiatingOccupancyFraction=70
(表示在老年代使用率达到70%时触发CMS GC)。 -
-XX:+UseCMSInitiatingOccupancyOnly
:仅在老年代使用率达到设定值时才启动CMS GC,而不是使用默认的预测模型。 -
-XX:ParallelGCThreads
:设置ParNew GC的线程数,通常设置为CPU核心数的1到2倍。
例如:-XX:ParallelGCThreads=8
(根据CPU核数调整)。 -
-XX:CMSFullGCsBeforeCompaction
:设置在多少次Full GC后进行一次压缩以减少碎片化。
例如:-XX:CMSFullGCsBeforeCompaction=5
。
-
Serial GC
-
全称:Serial Garbage Collector
-
特点:
- 年轻代和老年代收集:Serial GC是单线程的,使用标记-清除算法(Mark-Sweep-Compact),进行串行的垃圾收集。每次垃圾收集时,所有应用线程都将暂停。
- 目标:最小化内存开销,适合单核CPU和小内存环境。
-
适用场景:
- 嵌入式系统、低资源环境、小型应用程序。
-
优化建议:
- 适用于小内存和低并发的场景,优化空间有限。
-
推荐参数 Serial GC 适用于低资源环境。推荐的参数设置:
-
-Xms
** 和 **-Xmx
:根据系统资源设置较小的堆内存。
例如:-Xms512m -Xmx512m
。 -
-XX:+UseSerialGC
:使用Serial GC。
-
G1 GC
-
全称:Garbage First Garbage Collector
-
特点:
- 年轻代和老年代收集:G1 GC通过分区收集(Region-based)方式将内存分成多个区域,逐步回收和压缩内存。它在年轻代和老年代都使用标记-整理(Mark-Compact)算法。
- 目标:提供可预测的暂停时间,平衡吞吐量和延迟,适合大堆内存环境。
- 优势:能够减少长时间的Full GC停顿,适合对吞吐量和延迟都有要求的场景。
-
适用场景:
- 大堆内存、高并发、对暂停时间和吞吐量都有要求的应用,如大型服务器应用、在线交易系统。
-
优化建议:
- 使用
-XX:MaxGCPauseMillis
来设置暂停时间的目标。 - 调整
-XX:G1ReservePercent
来控制保留的空闲区域,减少内存碎片。 - 结合
-XX:InitiatingHeapOccupancyPercent
设置什么时候开始并发标记阶段。
- 使用
-
推荐参数:G1 GC 适用于大堆内存和需要平衡延迟与吞吐量的应用。推荐的参数设置:
-
-XX:+UseG1GC
:启用G1 GC。 -
-Xms
** 和 **-Xmx
:设置为相同值,避免堆内存动态调整带来的性能开销。
例如:-Xms4096m -Xmx4096m
(根据应用需要调整)。 -
-XX:MaxGCPauseMillis
:设置目标最大GC暂停时间(毫秒)。G1 GC会尝试满足这个目标,但并不保证。
例如:-XX:MaxGCPauseMillis=200
(根据应用需求调整)。 -
-XX:InitiatingHeapOccupancyPercent
:设置在堆内存使用达到多少时触发并发标记周期。通常设置为40%到60%之间。
例如:-XX:InitiatingHeapOccupancyPercent=45
。 -
-XX:G1ReservePercent
:设置堆内存中保留的空闲区域比例,以减少内存碎片。默认值为10。
例如:-XX:G1ReservePercent=15
。 -
-XX:G1HeapRegionSize
:设置堆内存区域大小。通常建议设置为1MB到32MB之间,以更好地控制内存分配。
例如:-XX:G1HeapRegionSize=16m
。
-
总结
- Parallel GC:适用于高吞吐量,建议使用较大的GC线程数和调整暂停时间目标。
- ParNew GC + CMS GC:适用于低延迟应用,建议配置适当的触发阈值和线程数,避免内存碎片化。
- Serial GC:适用于低资源场景,配置简单,适合小型应用。
- G1 GC:适用于大堆内存和需要平衡延迟与吞吐量的应用,建议调整暂停时间目标和并发标记触发阈值。
选择合适的垃圾回收器
- 高吞吐量优先:
- 如果你的应用程序主要关注吞吐量,并且对停顿时间不敏感,选择Parallel GC。
- 低延迟优先:
- 如果应用对响应时间要求很高,如Web应用或实时系统,选择ParNew GC + CMS GC或G1 GC。G1 GC是一个更现代的选择,能够在大堆内存情况下提供较好的延迟管理。
- 低资源环境:
- 如果是在嵌入式系统或资源受限的环境中,Serial GC是一个简单且有效的选择。
- 混合场景:
- 如果需要在延迟和吞吐量之间取得平衡,并且你的应用有较大的堆内存,选择G1 GC。
综合优化建议
- 监控和调优:使用JVM调优工具(如JVisualVM、GC日志分析工具)监控应用的运行情况,并基于GC日志调整参数。
- 固定堆大小:对于某些应用,固定堆大小(相同的
-Xms
和-Xmx
)可以避免堆内存调整带来的额外开销。 - 分析内存使用模式:根据应用的对象分配模式,调整年轻代和老年代的内存分配策略。
- 定期测试:在不同的负载条件下测试GC策略,确保在实际生产环境中有最优的性能表现。
通过理解这些GC的特点和适用场景,结合应用的具体需求,选择合适的垃圾回收器并进行相应的调优可以显著提升应用的性能和稳定性。
其他优化建议
-XX:SurvivorRatio
:可以通过调整Survivor空间的比例来优化内存管理。默认值为8,表示新生代的1/8用于Survivor区。根据应用的对象生命周期分布,适当调整这个值可以减少垃圾回收的开销。-XX:MaxTenuringThreshold
:控制对象从新生代转移到老年代之前在Survivor区的最大年龄。较大的值可以减少对象进入老年代的频率,从而减少Full GC的频率。-XX:+UseStringDeduplication
:前提是使用-XX:+UseG1GC。如果应用中大量使用字符串,可以启用字符串去重功能,减少内存使用。
示例优化参数
根据上述建议,一个可能的优化方案如下:
-Xms2048m -Xmx2048m -XX:NewSize=768m -XX:MaxNewSize=768m -XX:+UseG1GC -XX:SurvivorRatio=6 -XX:MaxTenuringThreshold=10 -XX:+UseStringDeduplication
这个配置适合在2GB堆内存条件下运行,使用G1 GC进行垃圾回收,适当调整了新生代大小和Survivor空间比例,并启用了字符串去重功能。
最后
实际优化效果还需通过监控和调优工具(如JVM自带的JVisualVM、GC日志分析工具等)进行验证和调整,以满足应用的特定需求。