当前位置: 首页 > news >正文

性能优化 - 高级进阶:JVM 常见优化参数

文章目录

    • Pre
    • 1. 引言:Java版本演进与GC演变背景
    • 2. 查看JVM参数默认值的方法
    • 3. 基于ElasticSearch的JVM参数示例分析
      • 3.1 堆空间配置与AlwaysPreTouch
      • 3.2 堆外内存细分
      • 3.3 GC日志配置(Java 8 vs Java 9+)
      • 3.4 OOM时Dump配置
      • 3.5 垃圾回收器配置:CMS示例及迁移
      • 3.6 其他额外参数
    • 4. 常见GC器演进与配置要点
      • 4.1 CMS生命周期与参数
      • 4.2 G1配置要点
      • 4.3 ZGC、Shenandoah简介
      • 4.4 其他GC(Serial、Parallel等)
    • 5. 深入调优:分代比例、SurvivorRatio、TenuringThreshold等
    • 6. 小结与建议

在这里插入图片描述


Pre

性能优化 - 理论篇:常见指标及切入点

性能优化 - 理论篇:性能优化的七类技术手段

性能优化 - 理论篇:CPU、内存、I/O诊断手段

性能优化 - 工具篇:常用的性能测试工具

性能优化 - 工具篇:基准测试 JMH

性能优化 - 案例篇:缓冲区

性能优化 - 案例篇:缓存

性能优化 - 案例篇:数据一致性

性能优化 - 案例篇:池化对象_Commons Pool 2.0通用对象池框架

性能优化 - 案例篇:大对象的优化

性能优化 - 案例篇:使用设计模式优化性能

性能优化 - 案例篇:并行计算

性能优化 - 案例篇:多线程锁的优化

性能优化 - 案例篇:CAS、乐观锁、分布式锁和无锁

性能优化 - 案例篇: 详解 BIO NIO AIO

性能优化 - 案例篇: 19 条常见的 Java 代码优化法则

性能优化 - 案例篇:JVM垃圾回收器

性能优化 - 案例篇:JIT

性能优化 - 案例篇:11种优化接口性能的通用方案


1. 引言:Java版本演进与GC演变背景

Java 8长期以来是企业主力版本,很多公司因稳定性和兼容性选择Java 8并启用CMS垃圾回收器。但从Java 9开始进入半年一版的快速发布模式,Java 8与Java 11成为LTS版本,后续LTS如Java 17、Java 21等陆续推出([en.wikipedia.org][1], [preemptive.com][2])。

随着JVM内部不断演进,CMS在Java 9中被标记为Deprecated,并于Java 14正式移除(见JEP 363)([openjdk.org][3], [oracle.com][4])。新GC器如G1、ZGC、Shenandoah成熟,逐渐成为主流选择。
因此,在不同JVM版本上配置GC参数需先查看默认值,不要盲从他人建议。


2. 查看JVM参数默认值的方法

可以使用以下命令查看参数的默认值和当前生效参数:

java -XX:+PrintFlagsFinal -XX:+UseG1GC 2>&1 | grep UseAdaptiveSizePolicy

上述命令在启动时列出所有Flags的最终值,通过grep过滤目标参数。常见用法还有:

java -XX:+PrintCommandLineFlags -version

输出示例(Java 8默认Parallel GC):

-XX:InitialHeapSize=127905216 -XX:MaxHeapSize=2046483456 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
openjdk version "1.8.0_41"
...

通过这些命令可确认某个参数是否已有默认值,避免重复配置或无效配置。

3. 基于ElasticSearch的JVM参数示例分析

ElasticSearch(ES)作为典型Java应用,其jvm.options提供了常见配置案例,便于学习和参考。

3.1 堆空间配置与AlwaysPreTouch

ES常见配置:

-Xms1g
-Xmx1g
-XX:+AlwaysPreTouch

将-Xms与-Xmx设为相同值可避免动态扩容开销。在堆较大时,-XX:+AlwaysPreTouch会在JVM启动时触碰(touch)所有堆页面,提前向操作系统申请并锁定内存页,增加启动时间,但减少运行时动态分配时的性能损耗,提高稳定性和吞吐([docs.oracle.com][5])。

对于存储型服务(如ES),通常将堆设置为物理内存一半,以留一半给操作系统文件缓存(PageCache),提高I/O效率;对于计算型Web服务,可将堆设置为物理内存2/3,剩余1/3供直接内存、本地内存等使用。

在这里插入图片描述

JVM内存布局:堆与堆外细分、PageCache与JVM堆的关系。 堆外包含元空间、CodeCache、直接内存、本地内存(线程栈、网络缓冲等)及JNI分配等。

3.2 堆外内存细分

  • 元空间(Metaspace):通过-XX:MetaspaceSize-XX:MaxMetaspaceSize可指定初始化与上限;默认无上限可能导致过度使用系统内存,建议根据应用类加载行为适当设置上限。
  • JIT编译后代码存放 CodeCache:JIT编译后代码存储区,通过-XX:ReservedCodeCacheSize设置上限;若CodeCache满,会触发Full GC或影响性能。
  • 直接内存(Direct Memory):ByteBuffer等直接缓冲区申请内存,通过-XX:MaxDirectMemorySize限制,防止内存占用过大。
  • 本地内存(Native Memory):线程栈、JNI malloc、网络连接缓冲等,无法由JVM直接控制,但需关注高并发场景下的本地内存消耗。
  • JNI内存:依赖具体JNI实现,JVM无法控制,但应避免JNI库出现内存泄漏。

3.3 GC日志配置(Java 8 vs Java 9+)

在Java 8中,常用GC日志参数(以ES为例):

-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintTenuringDistribution
-XX:+PrintGCApplicationStoppedTime
-XX:-Xloggc:logs/gc.log
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=32
-XX:GCLogFileSize=64m

这些参数可打印GC细节、时间戳(系统时间)、年龄分布、STW停顿时间,并配置日志滚动([docs.oracle.com][5])。

Java 9+移除40多个GC日志参数,采用Unified Logging:

-Xlog:gc*,gc+age=trace,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m

此方式更统一、灵活,可通过jcmd动态调整([foojay.io][6])。

3.4 OOM时Dump配置

ES常见:

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=data
-XX:ErrorFile=logs/hs_err_pid%p.log

发生OOM时自动生成堆转储文件,用于后续MAT等工具分析问题根因。正常可使用jmap等命令获取堆快照,但生产环境优先配置自动Dump。

3.5 垃圾回收器配置:CMS示例及迁移

ES默认曾使用CMS:

-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly
  • UseConcMarkSweepGC表示Young代用ParNew,Old代用CMS。
  • CMSInitiatingOccupancyFraction设定启动并发标记的老年代占用阈值,避免Concurrent Mode Failure;需配合UseCMSInitiatingOccupancyOnly生效。

另外,对于 CMS 垃圾回收器,常用的还有下面的配置参数:

-XX:+ExplicitGCInvokesConcurrent
-XX:CMSFullGCsBeforeCompaction=0
-XX:+CMSScavengeBeforeRemark
-XX:+ParallelRefProcEnabled
  • -XX:ExplicitGCInvokesConcurrent 当代码里显示的调用了 System.gc(),实际上是想让回收器进行FullGC,如果发生这种情况,则使用这个参数开始并行 FullGC。建议加上。

  • -XX:CMSFullGCsBeforeCompaction 默认为 0,就是每次FullGC都对老年代进行碎片整理压缩,建议保持默认。

  • -XX:CMSScavengeBeforeRemark 开启或关闭在 CMS 重新标记阶段之前的清除(YGC)尝试。可以降低 remark 时间,建议加上。

  • -XX:+ParallelRefProcEnabled 可以用来并行处理 Reference,以加快处理速度,缩短耗时。

CMS在Java 14已移除,不可再用,应转向G1或更现代GC([blog.gceasy.io][7])。

3.6 其他额外参数

  • -Xss1m:设置线程栈大小为1MB,默认即1MB,可根据线程数和调用深度适当调整。
  • -XX:-OmitStackTraceInFastThrow:ES关闭此项以便调试异常;开启可合并重复异常栈以提高性能,但调试困难。
  • -Djava.awt.headless=true:服务器无GUI时需设置Headless模式,避免AWT初始化失败。
  • 其他-D参数如-Dfile.encoding=UTF-8、-Des.networkaddress.cache.ttl=60等,根据应用需求配置网络、编码、临时目录、日志框架等。

4. 常见GC器演进与配置要点

4.1 CMS生命周期与参数

CMS自Java 1.4.1起被引入,目标低延迟,但不压缩老年代容易产生碎片、发生Concurrent Mode Failure导致长STW。Java 9开始Deprecated,Java 14移除(JEP 363)([openjdk.org][3], [oracle.com][4])。建议迁移至G1等。

4.2 G1配置要点

G1自Java 7u14实验性引入,Java 9起默认GC。优点:并发标记、分区回收、自动压缩,提供MaxGCPauseMillis目标设置。常见参数:

  • -XX:+UseG1GC
  • -XX:MaxGCPauseMillis=<期望毫秒>
  • -XX:G1HeapRegionSize=<2的幂,默认通常合适,不建议轻易修改>
  • -XX:InitiatingHeapOccupancyPercent=<启动并发标记阈值,默认45%>
  • -XX:ConcGCThreads=<默认即可>
    G1无需手动设置-Xmn,自动调优分代大小;可通过打印日志分析GC行为,调整Pause目标和Region大小。

4.3 ZGC、Shenandoah简介

  • ZGC:Java 11实验性,Java 15生产就绪,面向超大堆和低停顿(通常<10ms)。使用-XX:+UseZGC启用,需JDK对应版本支持。
  • Shenandoah:类似目标,Java 12实验,Java 15+成熟。
    这些GC适用于大内存、低延迟场景,但需确认应用和平台支持。

4.4 其他GC(Serial、Parallel等)

  • Serial GC(-XX:+UseSerialGC):小堆、单线程场景。
  • Parallel GC(-XX:+UseParallelGC / UseParallelOldGC):追求吞吐,适合批处理。
    选择需根据应用类型(交互型、批处理、超大堆等)决定。

5. 深入调优:分代比例、SurvivorRatio、TenuringThreshold等

  • -Xmn:调整年轻代大小,G1一般无需;在Parallel或CMS可根据业务调整,若对象存活率低可加大年轻代。
  • -XX:SurvivorRatio:Eden和Survivor区比例,默认8,可根据对象晋升行为调整。
  • -XX:MaxTenuringThreshold:对象晋升阈值,CMS下默认6,G1下默认15;可通过-XX:+PrintTenuringDistribution观察年龄分布,若早期代晋升过多,适当降低阈值;若大多数对象在Survivor区很快死亡,适当增大可减少晋升压力。
  • PretenureSizeThreshold:大对象直接分配到老年代,使用少见。
    通过GC日志分析或可视化工具(如GCViewer、GCEasy)观察GC停顿、年轻代/老年代使用情况,再针对性调整。

6. 小结与建议

  • 在不同JVM版本和GC器上,先查看默认参数,不要盲信旧配置;
  • 根据应用类型(存储、计算、低延迟、高吞吐)选择合适堆大小及GC器;
  • 通过-XX:+PrintCommandLineFlags、PrintFlagsFinal、-Xlog或旧日志参数查看生效配置;
  • 合理配置元空间、CodeCache、直接内存等,防止本地内存耗尽;
  • 配置GC日志和OOM自动Dump,便于问题排查;
  • CMS已废弃,迁移至G1或更现代GC;
  • 深入调优需结合GC日志分析工具进行,调整分代比例、停顿目标、并发线程数等;
  • 在生产环境中小幅、渐进式调整,观察效果。
[1]: https://en.wikipedia.org/wiki/Java_version_history?utm_source=chatgpt.com "Java version history"
[2]: https://www.preemptive.com/blog/the-road-to-java-9/?utm_source=chatgpt.com "The Road to Java 9 - PreEmptive Solutions"
[3]: https://openjdk.org/jeps/363?utm_source=chatgpt.com "JEP 363: Remove the Concurrent Mark Sweep (CMS) Garbage ..."
[4]: https://www.oracle.com/java/technologies/javase/14-relnote-issues.html?utm_source=chatgpt.com "JDK 14 Release Notes - java - Oracle"
[5]: https://docs.oracle.com/en/java/java-components/enterprise-performance-pack/epp-user-guide/printing-jvm-information.html?utm_source=chatgpt.com "3 Printing JVM Information - Java - Oracle Help Center"
[6]: https://foojay.io/today/introduction-to-jvm-unified-logging-jep-158-jep-271/?utm_source=chatgpt.com "Introduction to JVM Unified Logging (JEP-158 / JEP-271) - Foojay.io"
[7]: https://blog.gceasy.io/cms-gc-algorithm-removed-from-java-14/?utm_source=chatgpt.com "CMS GC algorithm removed from Java 14?"

在这里插入图片描述

相关文章:

  • useMemo vs useCallback:React 性能优化的两大利器
  • 2024 提高寒假第一轮第四题:铁路建设
  • Uncaught (in promise) TypeError: x.isoWeek is not a function
  • 华为云国际版有区块链吗
  • 量化面试绿皮书:14. 钟表零件
  • Qt QComboBox下拉多选
  • Node.js 中常用的异步函数讲解、如何检测异步操作时间和事件
  • 「Matplotlib 入门指南」 Python 数据可视化分析【数据分析全栈攻略:爬虫+处理+可视化+报告】
  • 数据库相关操作
  • YOLOv11改进 | Conv/卷积篇 | 2024最新ECCV最新大感受野的小波卷积WTConv助力YOLOv11有效涨点(二次创新C3k2)
  • XXX2024073105:纪念品分组【c++】
  • 关于layui select option莫名多一行的问题
  • NodeJS哪些情况下会造成内存泄漏和避免方法
  • 建造者模式Builder Pattern
  • LeetCode HOT 100
  • ShenNiusModularity项目源码学习(34:总结)
  • 每日学习一道数模题-2024国赛E题-交通流量管控
  • React19源码系列之Hooks(useState)
  • C++ 类的知识点
  • 【Docker 05】Container - 容器
  • 好久不见在线观看免费高清/求好用的seo软件
  • 做英文简历的网站/搜狐财经峰会
  • 建设网站的服务项目/百家号权重查询
  • 中央人民政府门户网站建设理念/内容营销的4个主要方式
  • 以及在增加外链时应当注意什么?/班级优化大师下载安装app
  • 网站制作网页/网站搜索查询