jvm调优
温馨提示:
本文最后更新于 2026年04月01日,已超过 73 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我。
-Xms200M -Xmx200m
数值设置一样:防止内存抖动
jps 列出java的进程
jinfo java进程的信息 跟 pid
jstack 列出 java的堆栈信息 +pid
jstack 1958 | more jvm -参数
标准参数 所有的jvm版本全支持
java -X 非标准参数
java -XX: 常规的调优参数
查看 -XX 参数的个数 jdk11 668个
java -XX:+PrintFlagsFinal | wc -l 常用参数
GC常用参数
-Xmn -Xms -Xmx -Xss 年轻代 最小堆 最大堆 线程空间
-XX:+UseTLAB 使用TLAB,默认打开
-XX:+PrintTLAB 打印TLAB的使用情况
-XX:+TLABSize 设置TLAB大小
-XX:-DisableExplicitGC System.gc()不管用,FGC
-XX:+PrintGC 打印GC信息
-XX:+PrintGCDetails 打印GC详细信息
-XX:+PrintHeapAtGC 打印GC时堆状态
-XX:+PrintGCTimeStamps 打印GC时间戳
-XX:+PrintGCApplicationConcurrentTime(重要性低) 打印应用执行时间
-XX:+PrintGCApplicationStoppedTime(低) 打印暂停时长
-XX:+PrintReferenceGC(重要性低) 记录回收了多少种不同引用类型的引用
-verbose:class 类加载详细过程
-XX:+PrintVMOptions 打印JVM启动参数
-XX:+PrintFlagsFinal -XX:+PrintFlagsInitial 必须合用
-Xloggc:opt/log/gc.log GC日志输出路径
-XX:MaxTenuringThreshold 对象晋升年龄阈值
Parallel常用参数
-XX:SurvivorRatio 年轻代中Eden区与Survivor区的比例
-XX:PreTenureSizeThreshold 大对象直接进入老年代的阈值
-XX:MaxTenuringThreshold 对象晋升到老年代的最大年龄
-XX:+ParallelGCThreads 并行收集器的线程数,通常设置为CPU核心数相同
-XX:+UseAdaptiveSizePolicy 自动选择堆大小比例
CMS常用参数
-XX:+UseConcMarkSweepGC 启用CMS垃圾回收器
-XX:ParallelCMSThreads CMS线程数量
-XX:CMSInitiatingOccupancyFraction 使用多少比例的老年代后开始CMS收集,默认是68%(近似值),如果频繁发生Serial Old卡顿,应调小(触发CMS回收)
-XX:+CMSCompactAtFullCollection 在FGC时进行压缩
-XX:CMSFullGCsBeforeCompaction 多少次FGC之后进行压缩
-XX:+CMSClassUnloadingEnabled 启用类卸载功能
-XX:CMSInitiatingPermOccupancyFraction 达到什么比例时进行Perm回收
G1常用参数
-XX:+UseG1GC 启用G1垃圾回收器
-XX:MaxGCPauseMillis 建议值,G1会尝试调整Young区的块数来达到这个值
-XX:GCPauseIntervalMillis GC的间隔时间
-XX:+G1HeapRegionSize 分区大小,建议逐渐增大该值,1, 2, 4, 8, 16, 32。 随着size增加,垃圾的存活时间更长,GC间隔更长,但每次GC的时间也会更长。 G1做了改进(动态区域大小)
G1NewSizePercent 新生代最小比例,默认为5%
G1MaxNewSizePercent 新生代最大比例,默认为60%
GCTimeRatio GC时间建议比例,G1会根据这个值调整堆空间
ConcGCThreads 线程数量
InitializingHeapOccupancyPercent 启动G1时的堆空间占用比例 什么是 jvm调优
什么是调优?
根据需求进行JVM规划和预调优
优化运行JVM运行环境(慢,卡顿)
解决JVM运行过程中出现的各种问题(OOM) 内存泄漏:对象特别顽固,回收不掉,称 内存泄漏,泄漏过多,依然产生OOM。
调优命令
jps jinfo + pid [root@VM-24-12-centos ~]# jps
1601 Jps
15377 services-mybatisPlus_high_concurrency_scenarios-3.5.5.jar
26758 blog-admin.jar
26714 blog-web.jar
[root@VM-24-12-centos ~]# jinfo 26758
Java System Properties:
#Wed Apr 01 00:03:05 CST 2026
java.specification.version=17
sun.jnu.encoding=UTF-8
java.class.path=/root/oneblog/blog-admin.jar
java.vm.vendor=Oracle Corporation
LOG_PATH=/var/tmp/oneblog/blog-admin
sun.arch.data.model=64
sun.font.fontmanager=sun.awt.X11FontManager
catalina.useNaming=false
java.vendor.url=https\://java.oracle.com/
user.timezone=Asia/Shanghai
os.name=Linux
java.vm.specification.version=17
user.country=US
sun.java.launcher=SUN_STANDARD
sun.boot.library.path=/mydata/jdk17/lib
sun.java.command=/root/oneblog/blog-admin.jar
jdk.debug=release
sun.cpu.endian=little
user.home=/root
user.language=en
java.specification.vendor=Oracle Corporation
java.version.date=2021-10-19
java.home=/mydata/jdk17
file.separator=/
java.vm.compressedOopsMode=32-bit
line.separator=\n
java.specification.name=Java Platform API Specification
java.vm.specification.vendor=Oracle Corporation
java.awt.headless=true
java.protocol.handler.pkgs=org.springframework.boot.loader
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
java.runtime.version=17.0.1+12-LTS-39
user.name=root
path.separator=\:
os.version=3.10.0-1160.119.1.el7.x86_64
java.runtime.name=Java(TM) SE Runtime Environment
file.encoding=UTF-8
spring.beaninfo.ignore=true
java.vm.name=Java HotSpot(TM) 64-Bit Server VM
LOG_FILE=/var/tmp/oneblog/blog-admin/spring.log
java.vendor.url.bug=https\://bugreport.java.com/bugreport/
java.io.tmpdir=/tmp
catalina.home=/var/tmp/oneblog/blog-admin
java.version=17.0.1
user.dir=/root/oneblog
os.arch=amd64
java.vm.specification.name=Java Virtual Machine Specification
PID=26758
catalina.base=/var/tmp/oneblog/blog-admin
native.encoding=UTF-8
java.library.path=/mydata/jdk17/lib\:\:/usr/java/packages/lib\:/usr/lib64\:/lib64\:/lib\:/usr/lib
java.vm.info=mixed mode, sharing
java.vendor=Oracle Corporation
java.vm.version=17.0.1+12-LTS-39
sun.io.unicode.encoding=UnicodeLittle
java.class.version=61.0
VM Flags:
-XX:CICompilerCount=3 -XX:InitialHeapSize=134217728 -XX:MaxHeapSize=134217728 -XX:MaxNewSize=44695552 -XX:MinHeapDeltaBytes=196608 -XX:MinHeapSize=134217728 -XX:NewSize=44695552 -XX:NonNMethodCodeHeapSize=5832780 -XX:NonProfiledCodeHeapSize=122912730 -XX:OldSize=89522176 -XX:ProfiledCodeHeapSize=122912730 -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:SoftMaxHeapSize=134217728 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseSerialGC
VM Arguments:
jvm_args: -Xms128m -Xmx128m -XX:+UseSerialGC
java_command: /root/oneblog/blog-admin.jar
java_class_path (initial): /root/oneblog/blog-admin.jar
Launcher Type: SUN_STANDARD jstack pid 线程堆栈信息
CPU飙高 常用的排查方法
阿里规范:创建线程或线程池的时候,必须使用具有意义的名称。 方便在排查问题的时候,知道是哪部分出现的问题。
图形工具:jconsole、jvisualVM。 ==>生产中 服务器基本没有 显示器。所以都是用 非图形化的分析工具。
使用 arthas 的 dashboard ,可以清楚发现 CPU占用较高的一个或多个线程。
分析是 系统线程 还是 用户线程。
| 线程种类 | 可能的原因 | |||
|---|---|---|---|---|
| 系统线程 | 垃圾回收器忙碌却干不了事 | GC:PSPO--是否垃圾较多,忙不过来。 CMS--回收超过98%,就会down掉 | ||
| 业务线程 | 查看是否存在死循环 |
阿里分析工具 arthas
linux下安装
curl -L https://arthas.aliyun.com/install.sh | sh 可能出现的问题
[root@VM-24-12-centos ~]# ./as.sh
Arthas script version: 4.1.8
[INFO] JAVA_HOME: /mydata/jdk17
Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 15377 services-mybatisPlus_high_concurrency_scenarios-3.5.5.jar
[2]: 10746 /root/oneblog/blog-web.jar
[3]: 10782 /root/oneblog/blog-admin.jar
1
Arthas home: /root/.arthas/lib/4.1.8/arthas
Calculating attach execution time...
Attaching to 15377 using version /root/.arthas/lib/4.1.8/arthas...
[ERROR] Start arthas failed, exception stack trace:
com.sun.tools.attach.AgentLoadException: Failed to load agent library: instrument was not loaded.libinstrument.so: cannot open shared object file: No such file or directory
at jdk.attach/sun.tools.attach.VirtualMachineImpl.execute(VirtualMachineImpl.java:224)
at jdk.attach/sun.tools.attach.HotSpotVirtualMachine.loadAgentLibrary(HotSpotVirtualMachine.java:95)
at jdk.attach/sun.tools.attach.HotSpotVirtualMachine.loadAgentLibrary(HotSpotVirtualMachine.java:120)
at jdk.attach/sun.tools.attach.HotSpotVirtualMachine.loadAgent(HotSpotVirtualMachine.java:148)
at com.taobao.arthas.core.Arthas.attachAgent(Arthas.java:122)
at com.taobao.arthas.core.Arthas.(Arthas.java:27)
at com.taobao.arthas.core.Arthas.main(Arthas.java:161)
attach to target jvm (15377) failed, check /root/logs/arthas/arthas.log or stderr of target jvm for any exceptions. 解决方案:
- arthas启动在jar启动之前,就是 重启下 项目。
- 添加环境变量
[root@VM-24-12-centos ~]# ls -la /mydata/jdk17/lib/libinstrument.so
-rw-r--r-- 1 10668 10668 50304 Sep 28 2021 /mydata/jdk17/lib/libinstrument.so
[root@VM-24-12-centos ~]# ls -la /mydata/jdk17/lib/libattach.so
-rw-r--r-- 1 10668 10668 12808 Sep 28 2021 /mydata/jdk17/lib/libattach.so
[root@VM-24-12-centos ~]# export LD_LIBRARY_PATH=/mydata/jdk17/lib:$LD_LIBRARY_PATH
[root@VM-24-12-centos ~]# ./as.sh 运行
./as.sh 结果
[root@node3 ~]# ./as.sh
Arthas script version: 4.0.5
[INFO] JAVA_HOME: /mydata/jdk-11
Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 27877 demo.jar 使用 内部的编号 这里输入1 ,enter。进入pid内部

Arthas home: /root/.arthas/lib/4.0.5/arthas
Calculating attach execution time...
Attaching to 27877 using version /root/.arthas/lib/4.0.5/arthas...
real 0m1.404s
user 0m0.603s
sys 0m0.057s
Attach success.
telnet connecting to arthas server... current timestamp is 1760808582
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
,---. ,------. ,--------.,--. ,--. ,---. ,---.
/ O \ | .--. ''--. .--'| '--' | / O \ ' .-'
| .-. || '--'.' | | | .--. || .-. |`. `-.
| | | || |\ \ | | | | | || | | |.-' |
`--' `--'`--' '--' `--' `--' `--'`--' `--'`-----'
wiki https://arthas.aliyun.com/doc
tutorials https://arthas.aliyun.com/doc/arthas-tutorials.html
version 4.0.5
main_class demo.jar
pid 27877
start_time 2025-10-19 01:01:23.936
currnt_time 2025-10-19 01:29:42.272 常用命令 dashboard (模拟仪表盘)
dashboard 会简单明了的展示 各线程、堆情况。
jvm 相当于 jinfo 的命令 列出 所有进程的详细信息。 会有 垃圾回收器使用的方法。
thread [arthas@27877]$ thread
Threads Total: 53, NEW: 0, RUNNABLE: 12, BLOCKED: 0, WAITING: 15, TIMED_WAITING: 10, TERMINATED: 0, Internal threa
ds: 16
ID NAME GROUP PRIORITY STATE %CPU DELTA_TIM TIME INTERRUPT DAEMON
-1 C1 CompilerThread0 - -1 - 0.42 0.000 0:4.660 false true
53 arthas-command-execute system 5 RUNNABLE 0.17 0.000 0:0.010 false true
-1 VM Periodic Task Thread - -1 - 0.05 0.000 0:1.150 false true
-1 Sweeper thread - -1 - 0.04 0.000 0:0.181 false true
15 Catalina-utility-2 main 1 WAITING 0.04 0.000 0:0.176 false false
14 Catalina-utility-1 main 1 TIMED_WAI 0.04 0.000 0:0.180 false false
24 magic-api-send-log-task main 5 TIMED_WAI 0.03 0.000 0:0.203 false false
16 container-0 main 5 TIMED_WAI 0.01 0.000 0:0.006 false false
-1 C2 CompilerThread0 - -1 - 0.01 0.000 0:19.381 false true
2 Reference Handler system 10 RUNNABLE 0.0 0.000 0:0.004 false true
3 Finalizer system 8 WAITING 0.0 0.000 0:0.000 false true
4 Signal Dispatcher system 9 RUNNABLE 0.0 0.000 0:0.000 false true
22 Attach Listener system 9 RUNNABLE 0.0 0.000 0:0.008 false true
43 arthas-timer system 9 WAITING 0.0 0.000 0:0.000 false true
46 arthas-NettyHttpTelnetBoots system 5 RUNNABLE 0.0 0.000 0:0.020 false true
47 arthas-NettyWebsocketTtyBoo system 5 RUNNABLE 0.0 0.000 0:0.000 false true
48 arthas-NettyWebsocketTtyBoo system 5 RUNNABLE 0.0 0.000 0:0.001 false true
49 arthas-shell-server system 9 TIMED_WAI 0.0 0.000 0:0.001 false true
50 arthas-session-manager system 9 TIMED_WAI 0.0 0.000 0:0.000 false true
52 arthas-NettyHttpTelnetBoots system 5 RUNNABLE 0.0 0.000 0:0.301 false true
17 mysql-cj-abandoned-connecti main 5 TIMED_WAI 0.0 0.000 0:0.048 false true
18 Druid-ConnectionPool-Create main 5 WAITING 0.0 0.000 0:0.000 false true
19 Druid-ConnectionPool-Destro main 5 TIMED_WAI 0.0 0.000 0:0.002 false true
20 Druid-ConnectionPool-Create main 5 WAITING 0.0 0.000 0:0.000 false true
21 Druid-ConnectionPool-Destro main 5 TIMED_WAI 0.0 0.000 0:0.002 false true
25 magic-api-websocket-clean-t main 5 TIMED_WAI 0.0 0.000 0:0.014 false false
26 http-nio-9999-BlockPoller main 5 RUNNABLE 0.0 0.000 0:0.106 false true
27 http-nio-9999-exec-1 main 5 WAITING 0.0 0.000 0:0.000 false true
28 http-nio-9999-exec-2 main 5 WAITING 0.0 0.000 0:0.000 false true
29 http-nio-9999-exec-3 main 5 WAITING 0.0 0.000 0:0.000 false true
30 http-nio-9999-exec-4 main 5 WAITING 0.0 0.000 0:0.000 false true
31 http-nio-9999-exec-5 main 5 WAITING 0.0 0.000 0:0.000 false true
32 http-nio-9999-exec-6 main 5 WAITING 0.0 0.000 0:0.000 false true
33 http-nio-9999-exec-7 main 5 WAITING 0.0 0.000 0:0.000 false true
34 http-nio-9999-exec-8 main 5 WAITING 0.0 0.000 0:0.000 false true
35 http-nio-9999-exec-9 main 5 WAITING 0.0 0.000 0:0.000 false true
36 http-nio-9999-exec-10 main 5 WAITING 0.0 0.000 0:0.000 false true
37 http-nio-9999-ClientPoller main 5 RUNNABLE 0.0 0.000 0:0.109 false true
38 http-nio-9999-Acceptor main 5 RUNNABLE 0.0 0.000 0:0.000 false true
41 DestroyJavaVM main 5 RUNNABLE 0.0 0.000 2:39.339 false false thread 线程ID ==> 可以查看具体的某个线程的信息
[arthas@27877]$ thread 2
"Reference Handler" Id=2 RUNNABLE
at java.base@11/java.lang.ref.Reference.waitForReferencePendingList(Native Method)
at java.base@11/java.lang.ref.Reference.processPendingReferences(Reference.java:241)
at java.base@11/java.lang.ref.Reference$ReferenceHandler.run(Reference.java:213) 一键查找死锁
thread -b 频繁FGC 怎么定位
Heap dump 将整个堆 到处到磁盘上。
heapdump 结果
[arthas@27877]$ heapdump
Dumping heap to /tmp/heapdump2025-10-19-02-004512530736780922531.hprof ...
Heap dump file created 将文件 下载达到 windows机器上,就可以使用 图形界面的分析工具了。
top
top 自带命令 可以观察 cpu、内存占用信息
jmap 查看对象 可以不用导出,直接分析对象
[root@node3 ~]# jmap -histo 27877 | head -20
num #instances #bytes class name (module)
-------------------------------------------------------
1: 260522 22126920 [B (java.base@11)
2: 31254 13010496 [I (java.base@11)
3: 45763 10481976 [Ljava.lang.Object; (java.base@11)
4: 185995 4463880 java.lang.String (java.base@11)
5: 161692 3880608 java.util.LinkedList$Node (java.base@11)
6: 38644 3400672 java.lang.reflect.Method (java.base@11)
7: 65532 2621280 java.util.LinkedHashMap$Entry (java.base@11)
8: 87492 2099808 com.taobao.text.util.Pair
9: 65588 2098816 java.util.concurrent.ConcurrentHashMap$Node (java.base@11)
10: 13097 2007880 [C (java.base@11)
11: 28946 1977360 [Ljava.util.HashMap$Node; (java.base@11)
12: 15795 1876400 java.lang.Class (java.base@11)
13: 51916 1661312 java.util.HashMap$Node (java.base@11)
14: 29598 1657488 java.util.LinkedHashMap (java.base@11)
15: 54776 1309776 [Lcom.taobao.text.util.Pair;
16: 31323 1252920 com.taobao.text.ui.LabelElement
17: 29234 935488 com.taobao.text.ui.LabelReader
18: 35048 797864 [Ljava.lang.Class; (java.base@11) 在程序崩溃之前,导出堆数据
java -Xms20M -Xmx20M -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError jad 反编译类 ---> 应急使用
jad cn.chengdu.test.entity.Backfile 例如
[arthas@27877]$ jad cn.chengdu.test.entity.Blog
ClassLoader:
+-org.springframework.boot.loader.LaunchedURLClassLoader@d2cc05a
+-jdk.internal.loader.ClassLoaders$AppClassLoader@799f7e29
+-jdk.internal.loader.ClassLoaders$PlatformClassLoader@610db97e
Location:
file:/root/demo.jar!/BOOT-INF/classes!/
/*
* Decompiled with CFR.
*
* Could not load the following classes:
* com.baomidou.mybatisplus.annotation.IdType
* com.baomidou.mybatisplus.annotation.TableField
* com.baomidou.mybatisplus.annotation.TableId
* com.baomidou.mybatisplus.annotation.TableName
* io.swagger.annotations.ApiModel
* io.swagger.annotations.ApiModelProperty
*/
package cn.chengdu.test.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
@TableName(value="blog")
@ApiModel(value="Blog对象", description="博客表")
public class Blog
implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value="序号")
@TableId(value="id", type=IdType.AUTO)
private Integer id;
@ApiModelProperty(value="博客内容")
@TableField(value="blogcontent")
private String blogcontent;
@ApiModelProperty(value="创建时间")
@TableField(value="maketime")
private String maketime;
@ApiModelProperty(value="浏览次数")
@TableField(value="lookdegree")
private Integer lookdegree;
public void setId(Integer id) {
/*25*/ this.id = id;
}
public void setBlogcontent(String blogcontent) {
/*25*/ this.blogcontent = blogcontent;
}
public String getBlogcontent() {
/*40*/ return this.blogcontent;
}
public String getMaketime() {
/*44*/ return this.maketime;
}
public Integer getLookdegree() {
/*48*/ return this.lookdegree;
}
public void setMaketime(String maketime) {
/*25*/ this.maketime = maketime;
}
public void setLookdegree(Integer lookdegree) {
/*25*/ this.lookdegree = lookdegree;
}
Blog(Integer id, String blogcontent, String maketime, Integer lookdegree) {
this.id = id;
this.blogcontent = blogcontent;
this.maketime = maketime;
this.lookdegree = lookdegree;
}
public String toString() {
return "Blog(id=" + this.getId() + ", blogcontent=" + this.getBlogcontent() + ", maketime=" + this.getMaketime() + ", lookdegree=" + this.getLookdegree() + ")";
}
public static BlogBuilder builder() {
return new BlogBuilder();
}
public Integer getId() {
/*36*/ return this.id;
}
public static class BlogBuilder {
private Integer id;
private String blogcontent;
private String maketime;
private Integer lookdegree;
public BlogBuilder blogcontent(String blogcontent) {
this.blogcontent = blogcontent;
return this;
}
public BlogBuilder maketime(String maketime) {
this.maketime = maketime;
return this;
}
public BlogBuilder lookdegree(Integer lookdegree) {
this.lookdegree = lookdegree;
return this;
}
BlogBuilder() {
}
public String toString() {
return "Blog.BlogBuilder(id=" + this.id + ", blogcontent=" + this.blogcontent + ", maketime=" + this.maketime + ", lookdegree=" + this.lookdegree + ")";
}
public BlogBuilder id(Integer id) {
this.id = id;
return this;
}
public Blog build() {
return new Blog(this.id, this.blogcontent, this.maketime, this.lookdegree);
}
}
}
Affect(row-cnt:2) cost in 148 ms. redefine重新加载编译好的.class文件
redefine /tmp/MathGame.class 禁止手动GC
禁用显式 GC:通过 -XX:+DisableExplicitGC 参数可禁止 System.gc() 触发垃圾回收
正文到此结束
- 本文标签: Java
- 本文链接: http://119.91.109.247:8443//article/165
- 版权声明: 本文由张亚东原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权