JVM 参数调优

命令行

jps:查看正在运行的 Java 进程

  • 显式指定系统内所有 HotSpot 虚拟机进程(查看虚拟机进程信息)可用于查询正在运行的虚拟机进程。

  • 对于本地虚拟机来说 进行的本地虚拟机ID与操作系统的进行ID是一致的 唯一的

  • 使用测试:

    jps [-q] [-mlvV] []

    C:\Users\Admin>jps
    12624 Jps
    21316
    14380 Demo01
    
    • -q:仅仅展示虚拟机唯一id 不展示主类的名称等
    C:\Users\Admin>jps -q
    18016  // 每次使用jps的时候 进程id不一样
    21316
    14380
    
    • -m:输出虚拟机进程启动时 传递给主函数 main() 的参数
    C:\Users\Admin>jps -m
    12656 Jps -m
    14380 Demo01 666
    21316
    
    • -l:输出应用程序主类的全类名 如果是 jar包 展示完整路径
    C:\Users\Admin>jps -m
    15588 Jps -m
    21316
    20344 Launcher D:/Program Files/JetBrains/IntelliJ IDEA 2022.2/plugins/java/lib/jps-builders.jar;//...
    16908 Demo01 666
    
    • -v:列出虚拟机进程启动时的 JVM 参数。例如:-Xmx60m -Xms60m
    C:\Users\Admin>jps -v
    16908 Demo01 -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:63925,suspend=y,server=n -Xmx60m -Xms60m -javaagent:C:\Users\Admin\AppData\Local\JetBrains\IntelliJIdea2022.2\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8
    

jstat:查看 JVM 统计信息

  • 用于监视虚拟机各种运行状态的信息:类装载、内存、垃圾收集、JIT编译等运行数据。

  • 使用测试:

    jstat - [-t] [-h] [ []]

    • option 参数:

      C:\Users\Admin>jstat -options
      -class
      -compiler
      -gc
      -gccapacity
      -gccause
      -gcmetacapacity
      -gcnew
      -gcnewcapacity
      -gcold
      -gcoldcapacity
      -gcutil
      -printcompilation
      
      • -class:显式 ClassLoader 相关信息:类的装载数量和时间、卸载数量和时间、装载所消耗的时间
      C:\Users\Admin>jstat -class 16908
      Loaded  Bytes  Unloaded  Bytes     Time
       627  1246.7        0    0.0     0.06
      
      • -compiler:显式 JIT 编译过的方法、耗时等信息
      C:\Users\Admin>jstat -compiler 16908
      Compiled Failed Invalid   Time   FailedType FailedMethod
          90      0       0   0.02            0
      
      • -gc:显式与GC相关的堆信息。

      s0区总容量、s1区总容量、s0区使用容量、s1区使用容量

      EC:Eden区总容量、EU:Eden区使用容量

      OC:老年代总容量、OU:老年代使用容量

      MC:元空间总容量、MU:元空间使用容量

      CCSC:压缩类空间总容量、CCSU:压缩类空间使用容量

      YGC:年轻代回收次数、YGCT:年轻代回收消耗时间

      FGC:老年代回收次数、FGCT:老年代回收消耗时间

      GCT:垃圾回收消耗总时间

      C:\Users\Admin>jstat -gc 16908
      S0C     S1C     S0U   S1U   EC         EU       OC        OU    MC      MU     CCSC    CCSU   YGC
      2560.0  2560.0  0.0   0.0   15360.0    4498.2   40960.0   0.0   4480.0  787.4  384.0   76.6   0
      YGCT    FGC    FGCT     GCT
      0.000   0      0.000    0.000
      
      • -gccapacity:堆空间使用到的最大、最小空间

      NGCMN:新生代最小容量、NGCMX:新生代最大容量、NGC:当前新生代容量=>20480=2560(S0C) + 2560(S1C) + 15360(EC)

      OGCMN:老年代最小容量、OGCMX:老年代最大容量、OGC:当前老年代容量

      MCMN:方法区最小容量、MCMX:方法区最大容量、MC:当前方法区容量

      CCSMN:压缩类空间最小容量、CCSMX:压缩类空间最大容量、CCSC:当前压缩类空间容量

      jstat -gccapacity 16908
      NGCMN    NGCMX    NGC      S0C     S1C      EC        OGCMN     OGCMX     OGC       OC        MCMN   
      20480.0  20480.0  20480.0  2560.0  2560.0   15360.0   40960.0   40960.0   40960.0   40960.0   0.0 
      MCMX        MC       CCSMN   CCSMX       CCSC    YGC  FGC
      1056768.0   4480.0   0.0     1048576.0   384.0   0    0
      
      • -gcnew:新生代GC状况
      C:\Users\Admin>jstat -gcnew 16908
      S0C    S1C    S0U    S1U   TT  MTT  DSS  EC       EU      YGC   YGCT
      2560.0 2560.0 0.0    0.0   15  15   0.0  15360.0  4498.2  0     0.000
      
      • -gcnewcapacity:新生代使用到的最大、最小空间
      C:\Users\Admin>jstat -gcnewcapacity 16908
      NGCMN      NGCMX       NGC      S0CMX     S0C     S1CMX     S1C       ECMX        EC      YGC   FGC
      20480.0    20480.0    20480.0   6656.0   2560.0   6656.0   2560.0    19456.0    15360.0     0     0
      
      • -gcold:老年代GC状况
      C:\Users\Admin>jstat -gcold 16908
      MC       MU      CCSC     CCSU    OC        OU    YGC   FGC   FGCT    GCT
      4480.0   787.4   384.0    76.6    40960.0   0.0   0     0     0.000   0.000
      
      • -gcoldcapacity:老年代使用到的最大、最小空间
      C:\Users\Admin>jstat -gcoldcapacity 16908
      OGCMN       OGCMX       OGC        OC       YGC   FGC  FGCT    GCT
      40960.0     40960.0     40960.0    40960.0  0     0    0.000   0.000
      
      • -gcmetacapacity:元空间使用到的最大、最小空间
      C:\Users\Admin>jstat -gcmetacapacity 16908
      MCMN  MCMX         MC       CCSMN   CCSMX       CCSC    YGC   FGC  FGCT   GCT
      0.0   1056768.0    4480.0   0.0     1048576.0   384.0   0     0    0.000  0.000
      
      • -gcutil:关注已使用空间占总空间的百分比=> EC=15360 EU=4498.2 => 4498.2/15360 ≈ 29.29
      C:\Users\Admin>jstat -gcutil 16908
      S0     S1     E      O     M      CCS    YGC  YGCT    FGC  FGCT    GCT
      0.00   0.00  29.29   0.00  17.57  19.94  0    0.000   0    0.000   0.000
      
      • -gccause:相比 gcutil 多了发生 GC 的原因
      C:\Users\Admin>jstat -gccause 16908
      S0     S1    E      O     M      CCS    YGC  YGCT   FGC  FGCT   GCT    LGCC   GCC
      0.00   0.00  29.29  0.00  17.57  19.94  0    0.000  0    0.000  0.000  No GC  No GC
      
    • interval 参数:查询间隔 每隔1000ms统计一次

      C:\Users\Admin>jstat -class 16908 1000
      Loaded  Bytes   Unloaded  Bytes     Time
      627  	1246.7  0     	  0.0       0.06
      627  	1246.7  0     	  0.0       0.06
      627  	1246.7  0     	  0.0       0.06
      627  	1246.7  0     	  0.0       0.06
      
    • count 参数:指定查询的总次数

      C:\Users\Admin>jstat -class 16908 1000 2
      Loaded  Bytes   Unloaded  Bytes   Time
      627  	1246.7  0     	  0.0     0.06
      627  	1246.7  0     	  0.0     0.06
      
    • -t 参数:在输出信息前加一个时间戳表示程序运行的时间

      C:\Users\Admin>jstat -class -t 16908 1000 2
      Timestamp Loaded  Bytes   Unloaded  Bytes     Time
      3515.5    627  	  1246.7  0     	0.0       0.06
      3516.6    627     1246.7  0     	0.0       0.06
      
    • -h 参数:隔多少次周期输出一个表头信息

      C:\Users\Admin>jstat -class -t -h2 16908 1000 4
      Timestamp Loaded  Bytes   Unloaded  Bytes     Time
      3525.4    627  	  1246.7  0     	0.0       0.06
      3526.4    627  	  1246.7  0     	0.0       0.06
      Timestamp Loaded  Bytes   Unloaded  Bytes     Time
      3527.4    627  	  1246.7  0     	0.0       0.06
      3528.4    627  	  1246.7  0     	0.0       0.06
      

jinfo:实时查看和修改 JVM 配置参数

  • 查看虚拟机配置的参数信息

  • 使用测试:

    jinfo [option]

    • option 参数:
    -flag <name>         to print the value of the named VM flag
    -flag [+|-]<name>    to enable or disable the named VM flag
    -flag <name>=<value> to set the named VM flag to the given value
    -flags               to print VM flags
    -sysprops            to print Java system properties
    <no option>          to print both of the above
    
    // jinfo -flag 参数名称 进程id
    C:\Users\Admin>jinfo -flag MaxHeapSize 16908
    -XX:MaxHeapSize=62914560
    
    C:\Users\Admin>jinfo -flag UseG1GC 16908
    -XX:-UseG1GC
    
    // 查询vm曾经赋过值的参数
    C:\Users\Admin>jinfo -flags 16908
    Non-default VM flags: -XX:CICompilerCount=12 -XX:InitialHeapSize=62914560 //...
    
    // 系统参数
    C:\Users\Admin>jinfo -sysprops 16908
    

    并非所有参数都支持在运行时修改

jmap:导出堆映像文件&内存使用情况

  • 获取dump文件(堆存储快照文件、二进制文件)包括堆各区域的使用情况 堆中对象的统计信息 类加载信息

  • 使用测试:

    jmap [option]

    • option参数:
    <none>               to print same info as Solaris pmap
    -heap                to print java heap summary
    -histo[:live]        to print histogram of java object heap; if the "live"
                         suboption is specified, only count live objects
    -clstats             to print class loader statistics
    -finalizerinfo       to print information on objects awaiting finalization
    -dump:<dump-options> to dump java heap in hprof binary format
                         dump-options:
                           live         dump only live objects; if not specified,
                                        all objects in the heap are dumped.
                           format=b     binary format
                           file=<file>  dump heap to <file>
                         Example: jmap -dump:live,format=b,file=heap.bin <pid>
    -F                   force. Use with -dump:<dump-options> <pid> or -histo
                         to force a heap dump or histogram when <pid> does not
                         respond. The "live" suboption is not supported
                         in this mode.
    -h | -help           to print this help message
    -J<flag>             to pass <flag> directly to the runtime system
    
  • 导出映像文件:

    • 手动方式

      C:\Users\Admin>jmap -dump:format=b,file=d:/16908_1.hprof 16908
      Dumping heap to D:\16908_1.hprof ...
      Heap dump file created
      
      C:\Users\Admin>jmap -dump:live,format=b,file=d:/16908_2.hprof 16908
      Dumping heap to D:\16908_2.hprof ...
      Heap dump file created
      

      jmap 访问堆中的所有对象 为了保证在此过程中不被应用程序打扰 需要借助安全点机制

      :live 只统计堆中存活的对象 如果对象存活时间在两个安全点之间 那么将无法探知这些对象

  • 显式堆内存相关信息:

    • 显式当前时间点上的堆内存信息

      C:\Users\Admin>jmap -heap 16908
      
      Heap Configuration:
         MinHeapFreeRatio         = 0
         MaxHeapFreeRatio         = 100 //...
         
      Heap Usage:
      PS Young Generation
      Eden Space:
         capacity = 15728640 (15.0MB) //...
      
    • 显式当前堆中 类、实例数量、合计容量

      C:\Users\Admin>jmap -histo 16908
      
       num     #instances         #bytes  class name
      ----------------------------------------------
         1:           869        1947344  [B
         2:           683        1397816  [I
         3:          7186         756968  [C
         4:          5808         139392  java.lang.String
         5:           708          80344  java.lang.Class
         //...
      Total         21980        4606184
      

jhat:JDK 自带的堆分析工具

  • 用于分析 jmap 生成的 heap dump 文件。在 JDK9 中已被删除 官方建议使用 VisualVM代替。
C:\Users\Admin>jhat d:/16908_1.hprof
Reading from d:/16908_1.hprof...
Dump file created Wed Sep 27 21:00:41 CST 2023
Snapshot read, resolving...
Resolving 21979 objects...
Chasing references, expect 4 dots....
Eliminating duplicate references....
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

默认会在 7000 端口启动服务 可以使用 -port 修改端口号

在这里插入图片描述

jstack:打印JVM 中线程快照

  • 用于生成虚拟机指定线程当前时刻的线程快照
jstack 16908
2023-09-27 21:12:24
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.271-b09 mixed mode):

"Service Thread" #21 daemon prio=9 os_prio=0 tid=0x0000024e585f8000 nid=0x4bf0 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
C:\Users\Admin>jstack -l 16908
2023-09-27 21:12:17
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.271-b09 mixed mode):

"Service Thread" #21 daemon prio=9 os_prio=0 tid=0x0000024e585f8000 nid=0x4bf0 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   // 使用 -l 会多关于锁的附加信息
   Locked ownable synchronizers:
        - None

jcmd:多功能命令行

  • 多功能工具 可以实现前面 jstat 之外的所有命令功能。
  • 列出所有 JVM 进程
C:\Users\Admin>jcmd
16908 com.demo.Demo01 666
17964 sun.tools.jcmd.JCmd
  • 针对指定的进程 列出所有具体命令
C:\Users\Admin>jcmd 16908 help
16908:
The following commands are available:
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.native_memory
VM.check_commercial_features
VM.unlock_commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
VM.classloader_stats
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.finalizer_info
GC.heap_info
GC.run_finalization
GC.run
VM.uptime
VM.dynlibs
VM.flags
VM.system_properties
VM.command_line
VM.version
  • Thread.print=>可以替换 jstack指令
jcmd 16908 Thread.print
16908:
2023-09-27 21:20:48
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.271-b09 mixed mode):

"Service Thread" #21 daemon prio=9 os_prio=0 tid=0x0000024e585f8000 nid=0x4bf0 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
  • GC.heap_dump 可以替换 jmap中的-dump操作
C:\Users\Admin>jcmd 16908 GC.heap_dump d:/16908_3.hprof
16908:
Heap dump file created

监控工具

JConsole

C:\Users\Admin>jconsole
  • 概览:查看堆内存使用量、线程、类、CPU占用率
  • 内存:
    • 可以查看堆内存使用量:PS Old Gen、PS Eden Gen、PS Surivior Gen
    • 非堆内存使用量:Metaspace、Code Cache、Compressed Class Space
  • 线程:查看所有线程 并能够检查死锁
  • 类:查看某个时间范围内一共有多少类被加载
  • VM概要

Visual VM

C:\Users\Admin>jvisualvm
  • 查看 JVM 参数和系统属性
  • 生成/读取堆内存快照
  • 生成/读取线程快照
  • VisualGC 插件实现程序资源的实时监控

Eclipse MAT

  • histogram:展示了各个类的实例数目 以及这些实例 潜堆深堆的总和

  • thread_overview:查看系统中的 Java 线程、查看局部变量信息

  • thread_overview中的线程里的对象可以查看互相引用关系:with outgoing references、with incoming references

  • shallow heap:潜堆。指一个对象所消耗的内存。

    // int 4个字节、String 4个字节、history 4个字节
    // 对象头 在开启压缩的情况下 12个字节
    // 潜堆:12 + 12 = 24。正好是8字节对齐的。
    class Student {
        private int id;
        private String name;
        private List<WebPage> history = new ArrayList<>();
    }
    
  • retained heap:深堆。

    • 保留集:仅被对象A所持有的对象集合。

    • 深堆:对象的保留集中所有的对象的潜堆大小之和。

    • 对象的实际大小:

      下图中 A 的实际大小为 A+C+D 但深堆大小为 A + D

      同理 B 的实际大小为 A+C+E 但深堆大小为 B + E

      在这里插入图片描述

      在这里插入图片描述

      分析一下上图:elementData 的潜堆和深堆:

      潜堆:15个对象 * 4个字节 + 数组本身4个字节 + 对象头12个字节 = 76个字节 与8字节对齐 最终为80

      深堆:0、21、42、63、84、35、70。共7个对象不属于保留集中。还剩8个对象。其中7是144字节。其余为152字节。

      144 + 7 * 152 = 1208 + 80个字节的潜堆 = 1288

  • 支配树:支配树中的对象与对象之间的关系就是直接支配关系,也就是上一级是下一级的直接支配者。

    • 支配:所有对象B的路径都经过对象A 则认为对象A支配对象B
    • 直接支配:对象A是离对象B最近的一个对象

内存泄露

  • 严格意义:对象不被使用了 但是GC又不能回收
  • 宽泛意义:一些不好的实践导致对象的生命周期很长 导致OOM
  • 情况:
    1. 静态集合类
    2. 单例模式:单例的静态特性
    3. 内部类持有外部类:外部类不再使用了 但是被内部类被长期引用
    4. 各种链接:I/O、数据库、网络
    5. 改变哈希值
    6. 变量不合理的作用域
    7. 缓存泄露:对象引用放入缓存

JVM 运行时参数

  • 以 - 开头的参数
-server   				选择 "server" VM 默认 VM 是 server.
-verbose:[class|gc|jni] 启用详细输出
-version      			输出产品版本并退出
-X            			输出非标准选项的帮助
  • 以-X 开头的参数
-Xmixed           混合模式执行(默认)
-Xint             仅解释模式执行
-Xloggc:<file>    将 GC 状态记录在文件中(带时间戳)
-Xms<size>        设置初始 Java 堆大小
-Xmx<size>        设置最大 Java 堆大小
-Xss<size>        设置 Java 线程堆栈大小
  • 以-XX 开头的参数

    • 打印设置的 -XX 参数

      • -XX:+PrintCommandLineFlags:打印用户手动设置或则 JVM 自动设置的选项
      -XX:InitialHeapSize=62914560 -XX:MaxHeapSize=62914560 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
      
      • -XX:+PrintFlagsInitial:打印出所有选项的默认值
      • -XX:+PrintFlagsFinal:打印出所有选项最终的生效值
    • 设置栈的大小

      • -XX:ThreadStackSize=0 默认值为0 默认使用出厂值 基本上不会设置这个大小
    • 设置堆的参数(针对32G内存)

      • 设置堆初始空间 -XX:InitialHeapSize=536870912 = 512M
      • 设置堆最大空间 -XX:MaxHeapSize=8560574464 ≈ 8G
      • 设置年轻代初始空间 -XX:NewSize=178782208 = 170.5M
      • 设置年轻代最大空间 -XX:MaxNewSize=2853175296 = 2,721M
      • 设置Eden区与Surivivor区的比例 -XX:SurvivorRatio=8 默认为8:1:1
      • 自动选择各区大小 -XX:+UseAdaptiveSizePolicy 默认开启 为了满足 GC 的最大停顿时间
      • 设置老年代与年轻代的比例 -XX:NewRatio=2 默认为2:1
      • 设置对象进入老年代的阈值 -XX:MaxTenuringThreshold=15
    • 设置方法区的参数

      • 元空间初始大小 -XX:MetaspaceSize=21807104
      • 元空间最大大小 -XX:MaxMetaspaceSize=18446744073709486080
      • 开启压缩对象指针 -XX:+UseCompressedOops
      • 开启压缩类指针 -XX:+UseCompressedClassPointers
      • 设置 ClassSpace 大小 -XX:CompressedClassSpaceSize=1073741824 = 1G
    • 直接内存

      • -XX:MaxDirectMemorySize=0 默认值为0 和堆大小一样大
    • OOM 相关参数

      • 在发生 OOM 的时候生成一个 dump 文件 -XX:-HeapDumpOnOutOfMemoryError
      • 在 FullGC 之前生成一个 dump 文件 -XX:-HeapDumpBeforeFullGC
      • 指定导出的 dump 文件存放在哪 -XX:HeapDumpPath=
      • 指定一个可执行脚本 当OOM的时候执行 -XX:OnOutOfMemoryError=

GC 日志分析

参数

  • -XX:+PrintGCDetails:在发生垃圾回收的时候打印详细日志
  • -XX:+PrintGCTimeStamps:日志带时间戳

格式

前提:-Xms20m -Xmx20m

  • Minor GC

    [GC (Allocation Failure) [PSYoungGen: 5575K->508K(6144K)] 5575K->3688K(19968K), 0.0018884 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    
    • GC (Allocation Failure) :GC原因 => 新生代中没有足够区域能够存放需要分配的数据
    • [PSYoungGen: 5575K->508K(6144K)]:年轻代回收前->回收后(年轻代总大小)
    • 5575K->3688K(19968K):堆内存回收前->堆内存回收后(堆总大小)
    • 0.0018884 secs:Minor GC花费的时间
    • Times: user=0.00 sys=0.00, real=0.00 secs
      • user:CPU 用户态花费的时间:执行线程
      • sys:CPU 内核态花费的时间:和硬件交互
      • real:此次事件花费的总时间
  • Full GC

    [Full GC (Ergonomics) [PSYoungGen: 5612K->1000K(6144K)] [ParOldGen: 9063K->13659K(13824K)] 14675K->14660K(19968K), [Metaspace: 3803K->3803K(1056768K)], 0.0043151 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
    
    • Full GC (Ergonomics):GC原因 => JVM 自适应调整导致的GC
    • [PSYoungGen: 5612K->1000K(6144K)]:年轻代回收前->回收后(年轻代总大小)
    • [ParOldGen: 9063K->13659K(13824K)]:老年代回收前->回收后(老年代总大小)
    • 14675K->14660K(19968K):堆内存回收前->堆内存回收后(堆总大小)
    • [Metaspace: 3803K->3803K(1056768K)]:元空间回收前->元空间回收后(元空间总大小)
    • 0.0043151 secs:Full GC花费的时间

性能优化的步骤

  1. 性能监控:利用命令行或者监控工具
  2. 性能分析:对dump文件或者堆栈信息解析
  3. 性能调优:调整 JVM 参数 或者优化架构代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值