原创

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 对象晋升年龄阈值<br/>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回收<br/>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.<init>(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.

解决方案:

  1. arthas启动在jar启动之前,就是 重启下 项目。
  2. 添加环境变量
[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内部

<br/>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
thread 相当于 jstack 命令,列出所有的线程 名称、cpu的使用
[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)

<xmp id="3phmn">一键查找死锁

 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() 触发垃圾回收
正文到此结束