1、内存控制类:避免OOM的核心,这5个参数最关键

内存配置是JVM调优的第一步,配小了会OOM,配大了会浪费资源,核心是“堆内存”“直接内存”“元空间”这三块。

新手模板:如果是8G内存的服务,可配

-Xms5g -Xmx5g -Xmn2g 

-XX:MaxDirectMemorySize=1g 

-XX:MetaspaceSize=256m 

-XX:MaxMetaspaceSize=256m

2、GC优化类:减少GC停顿,G1GC配置看这6个参数

现在主流的GC算法是G1GC(适合大堆内存,如10G以上),样例里也是用的G1,核心是“控制GC停顿时间”“优化Region大小”“减少Full GC”。

1. -XX:+UseG1GC:开启G1垃圾收集器

◦ 这是基础开关,JDK9及以上默认就是G1,但JDK8需要显式配置;

◦ 适合堆内存较大(>4G)的服务,比如微服务、中间件,能有效控制GC停顿在100ms以内。

2. -XX:G1HeapRegionSize:G1的Region大小(G1把堆分成多个相等的Region)

◦ 样例-XX:G1HeapRegionSize=16m:每个Region是16M;

◦ 可选值是1M、2M、4M、8M、16M、32M,建议根据堆大小选:20G堆选16M,10G堆选8M,太小会导致Region数量太多(影响性能),太大则小对象回收不高效。

3. -XX:ParallelGCThreads:GC的并行线程数(回收时用多少线程,影响GC速度)

◦ 样例-XX:ParallelGCThreads=16:用16个线程做GC;

◦ 建议设为“CPU核心数的1/2~2/3”,比如32核CPU设16线程,避免GC线程占满CPU,影响业务线程。

4. -XX:+ExplicitGCInvokesConcurrent:让System.gc()调用并发GC(而非Full GC)

◦ 默认情况下,代码里调用System.gc()会触发Full GC(停顿时间长),加这个参数后,会用G1的并发GC来处理,减少停顿;

◦ 很多框架(如Spring、Dubbo)可能隐性调用System.gc(),建议加上这个参数。

5. -Dsun.rmi.dgc.server.gcInterval/

-Dsun.rmi.dgc.client.gcInterval:

RMI触发GC的间隔

◦ 样例设为2592000000ms(30天):避免RMI默认每小时触发一次Full GC;

◦ 生产环境建议设长一点(比如7天以上),减少不必要的GC。

6. -XX:+UseTransparentHugePages:开启透明大页(THP)

◦ 大页内存(通常2M/1G)能减少CPU的内存页表切换,提升性能;

◦ 注意:需要操作系统也开启THP

(Linux下echo always > 

/sys/kernel/mm/transparent_hugepage/enabled),否则参数不生效。

3、日志监控类:出问题能排查,这3个参数必须加

很多人忽略日志配置,出了OOM、GC频繁等问题时,连“为什么错”都不知道。核心是“OOM dump”“GC日志”这两个。

1. -XX:+HeapDumpOnOutOfMemoryError + -XX:HeapDumpPath:OOM时自动生成堆快照

◦ 样例:

-XX:+HeapDumpOnOutOfMemoryError 

-XX:HeapDumpPath=/home/admin/logs/java.hprof;

◦ 作用:一旦发生OOM,JVM会在指定路径生成java.hprof文件,用MAT工具打开就能分析“哪个对象占了太多内存”,是排查OOM的关键;

◦ 避坑点:路径要确保有写权限,否则生成不了快照。

2. 

-Xlog:gc*:/home/admin/logs/gc.log:time:

输出GC日志到文件

◦ 作用:记录GC的时间、类型、回收内存大小、停顿时间等信息,比如“2024-05-20T14:30:00.123+0800: [GC pause (G1 Evacuation Pause) (young), 0.012s]”;

◦ 格式解析:gc*表示输出所有GC相关日志,time表示每条日志带时间戳;

◦ 避坑点:建议按天切割日志(比如用gc-%t.log,%t是时间戳),避免日志文件太大(比如超过10G)。

3. 

-Dcom.sun.management.jmxremote.port/

-Dcom.sun.management.jmxremote.ssl/

-Dcom.sun.management.jmxremote.authenticate:

开启JMX监控

◦ 样例:

-Dcom.sun.management.jmxremote.port=9981 

-Dcom.sun.management.jmxremote.ssl=false 

-Dcom.sun.management.jmxremote.authenticate=false;

◦ 作用:可以用JConsole、VisualVM等工具远程连接JVM,实时查看堆内存、GC情况;

◦ 避坑点:生产环境建议开启SSL和认证(authenticate=true),否则有安全风险(端口暴露可能被攻击)。

4、系统属性类:适配应用场景,这3个参数常用

这类参数是-D开头的,主要用来配置应用的编码、超时时间等,根据业务需求调整,均属于JVM可识别的系统属性配置。

1. -Dfile.encoding=GB18030:设置默认文件编码

◦ 避免中文乱码的关键,根据业务场景选GB18030或UTF-8(如果是跨系统交互,建议用UTF-8);

◦ 避坑点:要和应用配置(如Spring的spring.http.encoding)保持一致,否则仍会乱码。

2. 

-Dsun.net.client.defaultConnectTimeout/

-Dsun.net.client.defaultReadTimeout:

设置默认网络超时

◦ 样例:

-Dsun.net.client.defaultConnectTimeout=10000(连接超时10秒)、

-Dsun.net.client.defaultReadTimeout=30000(读超时30秒);

◦ 作用:避免网络请求(如HTTP调用、数据库连接)因超时设置不当导致线程阻塞,比如调用第三方接口时,默认超时可能是无限期,加这个参数能强制超时。

3. -Djava.awt.headless=true:开启Headless模式

◦ 作用:在没有图形界面的服务器上(如Linux服务器),避免Java程序因调用图形相关API(如生成图片、PDF)而报错;

◦ 只要是服务器端应用,建议都加上这个参数。

5、为什么要懂JVM启动参数?新手常踩的3个坑

很多人觉得“参数抄别人的就行”,但实际会踩很多坑,懂参数配置能避免这些问题:

1. 避免“隐性OOM”:不是堆内存不够,而是直接内存没配置

比如用了NIO的DirectBuffer,但没设-XX:MaxDirectMemorySize,直接内存默认和堆内存一样大(比如20G),当直接内存用满时,会抛出OutOfMemoryError: Direct buffer memory,但很多人只会查堆内存,根本找不到问题——懂参数的话,就知道要显式配置直接内存。

2. 减少“GC频繁导致的性能抖动”

比如堆内存-Xms和-Xmx设得不一样(比如-Xms5g -Xmx20g),JVM启动时只分配5G,运行中不够了再扩容到20G,扩容过程会触发GC,导致服务性能抖动;如果设为相同值,就不会有这个问题。

3. 出问题能快速排查

没配

-XX:+HeapDumpOnOutOfMemoryError,发生OOM时只能重启服务,根本不知道“哪个对象占了内存”;没配GC日志,GC频繁时只能猜“是不是堆太小”,而有日志的话,用GCViewer工具分析就能知道“是新生代GC频繁还是老年代GC频繁”,针对性调优。

最后:给新手的通用参数模板(直接复制能用)

如果是8G内存的Java服务(比如微服务、Spring Boot应用),可以用这个模板,根据实际内存调整数值:

-server -Xms5g -Xmx5g -Xmn2g -XX:MaxDirectMemorySize=1g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:+UseG1GC -XX:G1HeapRegionSize=8m -XX:ParallelGCThreads=8 -XX:+ExplicitGCInvokesConcurrent -Dsun.rmi.dgc.server.gcInterval=604800000 -Dsun.rmi.dgc.client.gcInterval=604800000 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/admin/logs/java.hprof -Xlog:gc*:/home/admin/logs/gc-%t.log:time,level,tags:filecount=7,filesize=100m -Dcom.sun.management.jmxremote.port=9981 -Dcom.sun.management.jmxremote.ssl=true -Dcom.sun.management.jmxremote.authenticate=true -Dfile.encoding=UTF-8 -Dsun.net.client.defaultConnectTimeout=10000 -Dsun.net.client.defaultReadTimeout=30000 -Djava.awt.headless=true

其中filesize=100m表示单个GC日志文件最大100M,filecount=7表示最多保留7个文件(避免日志占满磁盘);路径部分可根据服务器实际目录调整。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐