Jvm性能调优工具使用
JVM之jps进程状况工具
显示当前所有java进程,类似于ps命令
options说明
- -q:只输出进程 ID
- -m:输出传入 main 方法的参数
- -l:输出完全的包名,应用主类名,jar的完全路径名
- -v:输出jvm参数
- -V:输出通过flag文件传递到JVM中的参数
jps 原理
java程序在启动以后,会在java.io.tmpdir指定的目录(临时目录)下,生成一个类似于hsperfdata_{$user}的文件夹,这个文件夹里(在Linux中为/tmp/hsperfdata_{$user}/),有几个文件,名字就是java进程的pid,因此列出当前运行的java进程,只是把这个目录里的文件名列一下而已。 至于系统的参数什么,就可以解析这几个文件获得jps失效原因
现象: 用ps -ef|grep java能看到启动的java进程,但是用jps查看却不存在该进程的id - 磁盘读写、目录权限问题 若该用户没有权限写/tmp目录或是磁盘已满,则无法创建/tmp/hsperfdata_userName/pid文件。或该文件已经生成,但用户没有读权限
- 临时文件丢失,被删除或是定期清理,对于linux机器,一般都会存在定时任务对临时文件夹进行清理,导致/tmp目录被清空
- java进程信息文件存储地址被设置,不在/tmp目录下 上面我们在介绍时说默认会在/tmp/hsperfdata_userName目录保存进程信息,但由于以上1、2所述原因,可能导致该文件无法生成或是丢失,所以java启动时提供了参数(-Djava.io.tmpdir),可以对这个文件的位置进行设置,而jps、jconsole都只会从/tmp目录读取,而无法从设置后的目录读物信息
JVM之jstat统计信息监控工具
options说明
- -class:显示ClassLoad的相关信息;
- -compiler:显示JIT编译的相关信息;
- -gc:显示和gc相关的堆信息;
- -gccapacity:显示各个代的容量以及使用情况;
- -gcmetacapacity:显示metaspace的大小
- -gcnew:显示新生代信息;
- -gcnewcapacity:显示新生代大小和使用情况;
- -gcold:显示老年代和永久代的信息;
- -gcoldcapacity:显示老年代的大小;
- -gcutil:显示垃圾收集信息;
- -gccause:显示垃圾回收的相关信息(通-gcutil),同时显示最后一次或当前正在发生的垃圾回收的诱因;
- -printcompilation:输出JIT编译的方法信息
OPTION | 描述 |
---|---|
class | 用于查看类加载情况的统计,显示加载class的数量,及所占空间等信息。 |
compiler | 查看HotSpot中即时编译器编译情况的统计 |
gc | 查看JVM中堆的垃圾收集情况的统计,可以显示gc的信息,查看gc的次数,及时间。其中最后五项,分别是young gc的次数,young gc的时间,full gc的次数,full gc的时间,gc的总时间。 |
gccapacity | 查看新生代、老生代及持久代的存储容量情况,可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小 |
gccause | 查看垃圾收集的统计情况(这个和-gcutil选项一样),如果有发生垃圾收集,它还会显示最后一次及当前正在发生垃圾收集的原因 |
gcmetacapacity | 显示关于metaspace大小的统计信息。 |
gcnew | 查看新生代垃圾收集的情况,new对象的信息 |
gcnewcapacity | 用于查看新生代的存储容量情况,new对象的信息及其占用量 |
gcold | 用于查看老生代及持久代发生GC的情况,old对象的信息 |
gcoldcapacity | 用于查看老生代的容量,old对象的信息及其占用量 |
gcpermcapacity | 用于查看持久代的容量,perm对象的信息及其占用量 |
gcutil | 查看新生代、老生代及持代垃圾收集的情况 |
printcompilation | 当前VM执行的信息 |
类加载统计 class
1 | [root@gpu02_6 yangbin]# jstat -class 12308 |
- Loaded:加载class的数量
- Bytes:所占用空间大小
- Unloaded:未加载数量
- Bytes:未加载占用空间
- Time:时间
编译统计 compiler
1
2
3[root@gpu02_6 yangbin]# jstat -compiler 12308
Compiled Failed Invalid Time FailedType FailedMethod
14812 5 0 94.03 1 java/util/TreeMap getEntry - Compiled:编译数量
- Failed:失败数量
- Invalid:不可用数量
- Time:时间
- FailedType:失败类型
- FailedMethod:失败的方法
垃圾回收统计 gc
1
2
3[root@gpu02_6 yangbin]# jstat -gc 12308
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
512.0 512.0 0.0 320.0 53760.0 12922.9 265728.0 55319.9 73728.0 69032.6 8960.0 8184.7 1521 15.311 3 0.310 15.621 - S0C:第一个幸存区的大小
- S1C:第二个幸存区的大小
- S0U:第一个幸存区的使用大小
- S1U:第二个幸存区的使用大小
- EC:伊甸园区的大小
- EU:伊甸园区的使用大小
- OC:老年代大小
- OU:老年代使用大小
- MC:方法区大小
- MU:方法区使用大小
- CCSC:压缩类空间大小
- CCSU:压缩类空间使用大小
- YGC:年轻代垃圾回收次数
- YGCT:年轻代垃圾回收消耗时间
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间
- GCT:垃圾回收消耗总时间
堆内存统计 gccapacity
1 | [root@gpu02_6 yangbin]# jstat -gccapacity 12308 |
- NGCMN:新生代最小容量
- NGCMX:新生代最大容量
- NGC:当前新生代容量
- S0C:第一个幸存区大小
- S1C:第二个幸存区的大小
- EC:伊甸园区的大小
- OGCMN:老年代最小容量
- OGCMX:老年代最大容量
- OGC:当前老年代大小
- OC:当前老年代大小
- MCMN:最小元数据容量
- MCMX:最大元数据容量
- MC:当前元数据空间大小
- CCSMN:最小压缩类空间大小
- CCSMX:最大压缩类空间大小
- CCSC:当前压缩类空间大小
- YGC:年轻代gc次数
- FGC:老年代GC次数
总结垃圾回收统计 gcutil【常用】
1 | [root@gpu02_6 yangbin]# jstat -gcutil 12308 |
- S0:幸存1区当前使用比例
- S1:幸存2区当前使用比例
- E:伊甸园区使用比例
- O:老年代使用比例
- M:元数据区使用比例
- CCS:压缩使用比例
- YGC:年轻代垃圾回收次数
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间
- GCT:垃圾回收消耗总时间
eg:gcnew、gcnewcapacity、gcold、gcmetacapacity等用法及返回结果和上述选项类似,不再赘述。重点掌握gcutil 的用法既可1
2
3
4
5
6
7
8
9
10
11
12# 每一秒输出一次Jvm信息
jstat -gcutil 12308 1000
# 返回结果:
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 62.50 40.02 20.82 93.63 91.35 1521 15.311 3 0.310 15.621
0.00 62.50 40.02 20.82 93.63 91.35 1521 15.311 3 0.310 15.621
0.00 62.50 40.02 20.82 93.63 91.35 1521 15.311 3 0.310 15.621
0.00 62.50 40.02 20.82 93.63 91.35 1521 15.311 3 0.310 15.621
0.00 62.50 40.02 20.82 93.63 91.35 1521 15.311 3 0.310 15.621
0.00 62.50 40.02 20.82 93.63 91.35 1521 15.311 3 0.310 15.621
0.00 62.50 40.02 20.82 93.63 91.35 1521 15.311 3 0.310 15.621
0.00 62.50 40.03 20.82 93.63 91.35 1521 15.311 3 0.310 15.621
JVM之jinfo获取Java配置信息
执行命令
1 | jinfo 12308 |
返回结果
1 | Debugger attached successfully. |
JVM之jmap内存映射工具
参数选项:
- -dump:[live,]format=b,file=
使用hprof二进制形式,输出jvm的heap内容到文件=. live子选项是可选的,假如指定live选项,那么只输出活的对象到文件 - -finalizerinfo 打印正等候回收的对象的信息.
- -heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况
- -histo[:live] 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量
- -permstat 打印classload和jvm heap长久层的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来
- -F 强迫.在pid没有相应的时候使用-dump或者-histo参数. 在这个模式下,live子参数无效
- -J 传递参数给jmap启动的jvm.
示例 jmap -heap 12308
返回值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[root@gpu02_6 yangbin]# jmap -heap 12308
Attaching to process ID 12308, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.144-b01
using thread-local object allocation.
Parallel GC with 23 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 8380219392 (7992.0MB)
NewSize = 174587904 (166.5MB)
MaxNewSize = 2793406464 (2664.0MB)
OldSize = 349700096 (333.5MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 55050240 (52.5MB)
used = 32079944 (30.59381866455078MB)
free = 22970296 (21.90618133544922MB)
58.27394031343006% used
From Space:
capacity = 524288 (0.5MB)
used = 327680 (0.3125MB)
free = 196608 (0.1875MB)
62.5% used
To Space:
capacity = 524288 (0.5MB)
used = 0 (0.0MB)
free = 524288 (0.5MB)
0.0% used
PS Old Generation
capacity = 272105472 (259.5MB)
used = 56647600 (54.02336120605469MB)
free = 215457872 (205.4766387939453MB)
20.818250946456526% used
31019 interned Strings occupying 3185528 bytes.
示例 jmap -histo:live 34940 | more
查找最费内存的对象
1 | num #instances #bytes class name |
上述输出信息中,查看最大内存对象。如果某个对象占用空间很大,比如超过了100Mb,应该着重分析,为何没有释放,是否存在内存泄漏等。该命令会造成jvm强制执行一次full gc,线上慎用,可以采取dump内存快照,线下采用可视化工具进行分析
示例 导出内存快照 jmap -dump:format=b,file=/data0/34940.dump 34940
导出的文件可以通过jhat、mat等工具分析,分析方法赞不赘述,读者可自行了解
JVM之jhat堆快照分析工具
jhat 命令与jmap搭配使用,用来分析map生产的堆快存储快照。jhat内置了一个微型http/Html服务器,可以在浏览器打开查看
1 | jhat heapDum.dump |
JVM之jstack堆栈跟踪工具
jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。
- -F 当进程挂起,执行jstack
命令没有任何输出后,将强制转储堆内的线程信息 - -m 在混合模式下,打印 java 和 native c/c++ 框架的所有栈信息
- -l 长列表。打印关于锁的附加信息,例如属于 java.util.concurrent 的 ownable synchronizers 列表
OOM内存泄露
java堆内的OOM异常是实际应用中常见的内存溢出异常,OOM的三种情况:
- 申请资源(内存)过小,不够用。
- 申请资源太多,没有释放。
- 申请资源过多,资源耗尽。比如:线程过多,线程内存过大等。
排查申请资源问题
查看新生代,老生代堆内存的分配大小以及使用情况,看是否本身分配过小
1
jmap -heap 11869
排查gc
排查gc特别是full gc情况下,各个分代内存情况
1 | # 每秒输出一次gc的分代内存分配情况,以及gc时间 |
查找最费内存的对象
命令
1 | jmap -histo:live 11869 | more |
导出内存快照分析
命令
1 | jmap -dump:format=b,file=/tmp/dump.dat 11869 |
java进程的线程快照信息
常用来分析内存占用高、死锁等问题
1 | jstack -l 11869 |
pstack
可以查看某个进程的当前线程栈运行情况,top -Hp
参考文档
https://my.oschina.net/u/1859679/blog/1552290
官方文档:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html