JVM调优

2023/5/19 Java

启动Java应用时,提前设置 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/xxx.hprof

# Dump Java heap to /path/to/xxx.hprof when an OutOfMemoryError exception is thrown
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/xxx.hprof -jar xxx.jar
1
2

# JDK Tools

JDK 17 Documentation (opens new window)

Java Platform, Standard Edition (Java SE) 8 (opens new window)

Java® Development Kit Version 17 Tool Specifications (opens new window)

Java SE Tools Reference for UNIX (opens new window)

# jps

jps(Java Virtual Machine Process Status Tool)是JDK 1.5提供的一个显示当前所有java进程pid的命令。

jps
1

# jinfo

jinfo(Java Virtual Machine Configuration Information)是JDK提供的查看进程信息的命令。

Usage:
    jinfo <option> <pid>
       (to connect to a running process)

where <option> is one of:
    -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 VM flags and system properties
    -? | -h | --help | -help to print this help message
1
2
3
4
5
6
7
8
9
10
11
12

# jstat

jstat,是java虚拟机统计信息工具。

jstat -options
-class             显示classLoader的相关信息
-compiler          显示JIT编译的相关信息
-printcompilation  输出JIT编译的方法信息
-gc                显示一GC有关的堆信息
-gccapacity        显示各个代的容量及使用情况
-gccause           显示垃圾收集相关信息,同时显示最后一次或者当前正在发生的垃圾收集诱发原因
-gcmetacapacity
-gcnew             显示新生代信息
-gcnewcapacity     显示新生代大小与使用情况
-gcold             显示老年代和永久代的信息
-gcoldcapacity     显示永久代的大小
-gcutil            显示垃圾收集信息

jstat -compiler -t -h10 15256 1000

jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
-t        时间戳
-h<lines> 隔lines行显示标题
vmid      vm进程id
interval  监控间隔
count     监控次数

# 表示每1000毫秒收集一次gc信息,共收集100次,每隔10行显示一次标题,且标题行带时间戳
jstat -gc -t -h10 17480 1000 100
Timestamp           S0C         S1C         S0U         S1U          EC           EU           OC           OU          MC         MU       CCSC      CCSU     YGC     YGCT     FGC    FGCT     CGC    CGCT       GCT
          254.6         0.0         0.0         0.0         0.0       1024.0          0.0       5120.0       4572.1      832.0      634.7     128.0      49.6      8     0.013     1     0.007     2     0.000     0.021
          255.6         0.0         0.0         0.0         0.0       1024.0          0.0       5120.0       4572.1      832.0      634.7     128.0      49.6      8     0.013     1     0.007     2     0.000     0.021
          256.6         0.0         0.0         0.0         0.0       1024.0          0.0       5120.0       4572.1      832.0      634.7     128.0      49.6      8     0.013     1     0.007     2     0.000     0.021
          257.7         0.0         0.0         0.0         0.0       1024.0          0.0       5120.0       4572.1      832.0      634.7     128.0      49.6      8     0.013     1     0.007     2     0.000     0.021
          258.7         0.0         0.0         0.0         0.0       1024.0          0.0       5120.0       4572.1      832.0      634.7     128.0      49.6      8     0.013     1     0.007     2     0.000     0.021
          259.7         0.0         0.0         0.0         0.0       1024.0          0.0       5120.0       4572.1      832.0      634.7     128.0      49.6      8     0.013     1     0.007     2     0.000     0.021
          260.7         0.0         0.0         0.0         0.0       1024.0          0.0       5120.0       4572.1      832.0      634.7     128.0      49.6      8     0.013     1     0.007     2     0.000     0.021
S0C  - Heap上的 Survivor space 0 幸存0区总容量
S1C  - Heap上的 Survivor space 1 幸存1区总容量
S0U  - Heap上的 Survivor space 0 幸存0区已使用容量
S1U  - Heap上的 Survivor space 1 幸存1区已使用容量
EC   - Heap上的 Eden space 伊甸园区总容量
EU   - Heap上的 Eden space 伊甸园区已使用容量
OC   - Heap上的 Old space 老年代总容量
OU   - Heap上的 Old space 老年代已使用容量
MC   - 元数据区总容量
MU   - 元数据区已使用容量
CCSC - 压缩类空间总容量
CCSU - 压缩类空间已使用容量
YGC  - 从应用程序启动到采样时发生 Full GC 的次数
YGCT - 从应用程序启动到采样时 Full GC 所用的时间(单位秒)  
FGC  - 从应用程序启动到采样时发生 Full GC 的次数 
FGCT - 从应用程序启动到采样时 Full GC 所用的时间(单位秒)  
CGC  - 从应用程序启动到采样时 Concurrent GC 的次数  
CGCT - 从应用程序启动到采样时 Concurrent GC 所用的时间(单位秒)
GCT  - 从应用程序启动到采样时 GC 所用的总时间(单位秒)           

# 表示每1000毫秒收集一次jvm内存和gc信息,共收集100次,每隔10行显示一次标题,且标题行带时间戳
jstat -gcutil -t -h10 9928 1000 100
Timestamp         S0     S1     E      O      M     CCS    YGC     YGCT     FGC    FGCT     CGC    CGCT       GCT
           17.0   0.00  81.59   0.00  42.82  76.29  38.73      4     0.005     0     0.000     0     0.000     0.005
           18.1   0.00  81.59   0.00  42.82  76.29  38.73      4     0.005     0     0.000     0     0.000     0.005
           19.1   0.00  81.59   0.00  42.82  76.29  38.73      4     0.005     0     0.000     0     0.000     0.005
           20.1   0.00  81.59   0.00  42.82  76.29  38.73      4     0.005     0     0.000     0     0.000     0.005
           21.1   0.00  81.59   0.00  42.82  76.29  38.73      4     0.005     0     0.000     0     0.000     0.005
S0   — Heap上的 Survivor space 0 幸存0区当前使用比例     
S1   — Heap上的 Survivor space 1 幸存1区当前使用比例     
E    — Heap上的 Eden space 伊甸园区当前使用比例    
O    — Heap上的 Old space 老年代当前使用比例     
M    - 元数据区当前使用比例 
CCS  - 压缩使用比例
YGC  — 从应用程序启动到采样时发生 Young GC 的次数 
YGCT – 从应用程序启动到采样时 Young GC 所用的时间(单位秒)     
FGC  — 从应用程序启动到采样时发生 Full GC 的次数 
FGCT – 从应用程序启动到采样时 Full GC 所用的时间(单位秒)  
CGC  - 从应用程序启动到采样时 Concurrent GC 的次数 
CGCT - 从应用程序启动到采样时 Concurrent GC 所用的时间(单位秒)  
GCT  — 从应用程序启动到采样时 GC 所用的总时间(单位秒) 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

# jstack

jstack (opens new window) - print Java stack traces of Java threads for a specified Java process

jstack pid | more
1

# jmap

jmap (opens new window) - print details of a specified process

# 打印前20行堆中对象的统计信息,包括实例个数、大小、类名
jmap -histo pid | head -n 20

# 导出堆转储快照,使用jvisualvm等图形化工具分析
jmap -dump:live,format=b,file=heap.hprof pid
1
2
3
4
5

# Arthas

https://arthas.aliyun.com/doc/ (opens new window)

# JVM调优

  1. 定位消耗系统资源的进程,使用Linux的 top 命令;
  2. 定位是否有线程在吃CPU、占内存、发生死锁等等。

# CPU过高

  1. 使用 top 定位消耗系统资源的进程;
  2. 使用 top -H -p pid 定位CPU占用过高的线程tid;
  3. 使用 pstack tid 或者 strace -f -p tid 定位线程堆栈。

# OOM定位

  1. 使用 top 定位消耗系统资源的进程;

  2. 使用 jmap -histo pid | head -n 20 找出占内存的类;

  3. 使用 jmap -dump:live,format=b,file=heap.hprof pid 导出堆转储,使用jvisualvm等图形化工具分析。