0%

监控工具

监控工具

jvm自带的命令

jps命令

jps可以查看正在运行的java进程,并显示虚拟机执行主类的名称

1
2
3
4
5
6
jps [-q] [-mlvV] [<hostid>]

-q 仅显示java进程id,不显示主类的名称
-l 输出应用程序主类的全类名或jar包的完整路径
-m 输出虚拟机进程启动时传递给主类main()的参数
-v 列出虚拟机进程启动时的JVM参数

如果java程序启动 -XX:-UsePerfData,jps将无法探知到该java进程

jstat命令

jstat可以查看JVM的统计信息,监视虚拟机各种运行状态信息,可以展示出本地或者远程虚拟机进程的类装载、内存、垃圾收集、JIT编译等运行数据,常用于检测垃圾回收问题以及内存泄漏问题

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
Usage: jstat -help|-options
# -t 可以在输出信息前加上一个Timestamp列,显示运行时间,单位s
# -h 可以在周期性数据输出时,输出多少行数据后输出一个表头信息
# interval 查询的时间间隔,单位默认毫秒
# count 查询的次数
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

Definitions:
<option> An option reported by the -options option
<vmid> Virtual Machine Identifier. A vmid takes the following form:
<lvmid>[@<hostname>[:<port>]]
Where <lvmid> is the local vm identifier for the target
Java virtual machine, typically a process id; <hostname> is
the name of the host running the target Java virtual machine;
and <port> is the port number for the rmiregistry on the
target host. See the jvmstat documentation for a more complete
description of the Virtual Machine Identifier.
<lines> Number of samples between header lines. 每隔多少行输出一次表头信息
<interval> Sampling interval. The following forms are allowed:
<n>["ms"|"s"]
Where <n> is an integer and the suffix specifies the units as
milliseconds("ms") or seconds("s"). The default units are "ms".
指定输出统计数据的周期,可以是ms或者s,默认是ms
<count> Number of samples to take before terminating. 指定查询的总次数
-J<flag> Pass <flag> directly to the runtime system.


可用选项
1
2
# 查看jstat的可用选项
jstat -options
-class选项

显示ClassLoader的相关信息,如类的装载、卸载数量、总空间、类装载所消耗的空间

1
2
3
4
5
6
7
8
9
10
jstat -class 2713
Loaded Bytes Unloaded Bytes Time
700 1390.2 0 0.0 0.13

---
Loaded 被读入类的数量
Bytes 被读入的字节数K
Unloaded 被卸载的字节数K
Bytes 被卸载的字节数K
Time 花费在load和unload类的时间
-compiler

显示JIT编译器编译过的方法、耗时等信息

1
2
3
4
5
6
7
8
9
10
11
jstat -compiler 27087
Compiled Failed Invalid Time FailedType FailedMethod
15128 6 0 91.13 1 com/mysql/jdbc/AbandonedConnectionCleanupThread run

---
Compiled 被执行的编译任务的数量
Failed 失败的编译任务的数量
Invalid 无效的编译任务的数量
Time 花费在执行编译任务的时间
FailedType 最近失败编译的编译类名
FailedMethod 最近失败编译的方法名
-gc

显示与GC相关的堆信息,包括Eden区、Survivor区、老年代、永久代等的容量、已用空间、GC时间合计等信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
jstat -gc 2713   
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
154816.0 154816.0 0.0 154816.0 1238656.0 1109939.1 2572288.0 218975.9 79812.0 77988.1 9928.0 9352.9 23 3.184 5 0.339 3.523

---
S0C 当前S0的容量K
S1C 当前S1的容量K
S0U S0的使用K
S1U S1的使用K
EC 当前eden的容量K
EU eden的使用K
OC 当前old的容量K
OU old的使用K
MC 元空间的容量K
MU 元空间的使用K
CCSC 压缩类空间大小
CCSU 压缩类空间使用大小
YGC young gc次数
YGCT young gc花费的时间
FGC full gc次数
FGCT full gc花费的时间
GCT 垃圾收集的总时间

-gccapacity

显示内容与-gc基本相同,输出的主要关注点是java堆各个区域使用到的最大、最小空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
jstat -gccapacity 2713
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC
43520.0 698880.0 43520.0 5120.0 5120.0 33280.0 87552.0 1398272.0 87552.0 87552.0 0.0 1056768.0 4480.0 0.0 1048576.0 384.0 0 0

---
NGCMN 年轻代的最小容量K
NGCMX 年轻代的最大容量K
NGC 当前年轻代的容量K
S0C 当前S0的容量
S1C 当前S1的容量
EC 当前eden空间
OGCMN 老年代的最小容量
OGCMX 老年代的最大容量
OGC 当前老年代的容量
OC 当前来年代的空间
MCMN 元空间的最小容量
MCMX 元空间的最大容量
MC 当前元空间的容量
CCSMN 最小压缩类空间大小
CCSMX 最大压缩类空间大小
CCSC 当前压缩类空间容量
YGC young gc次数
FGC full gc次数
-gcutil

显示内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

jstat -gcutil 2713
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
60.11 0.00 22.51 10.78 97.72 94.21 24 3.698 5 0.339 4.037

---
S0 S0使用百分比
S1 S1使用百分比
E eden使用百分比
O old使用百分比
M 元空间使用百分比
CCS 压缩使用比例
YGC young gc次数
YGCT young gc时间
FGC full gc次数
FGCT full gc时间
GCT 垃圾收集总时间
-gccause

垃圾收集统计,与-gcutil功能相同,但会额外输出导致最后一次或当前正在发生的GC产生的原因(LGCC 和GCC两列)

1
2
3
4
5
6
7
jstat -gccause 2713   
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT LGCC GCC
60.11 0.00 1.04 10.78 97.72 94.21 24 3.698 5 0.339 4.037 Allocation Failure No GC

---
LGCC 最近垃圾回收的原因
GCC 当前垃圾回收的原因
-gcmetacapacity

元空间容量状况

1
2
3
jstat -gcmetacapacity 27087
MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT GCT
0.0 1120256.0 79812.0 0.0 1048576.0 9928.0 24 5 0.339 4.037
-gcnew

显示新生代GC状况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
jstat -gcnew 2713  
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
5120.0 5120.0 0.0 0.0 15 15 0.0 33280.0 5370.0 0 0.000


---
S0C 当前S0空间
S1C 当前S1空间
S0U S0空间使用
S1U S1空间使用
TT 对象在新生代存活次数
MTT 对象在新生代存活最大次数
DSS 希望的Survivor大小
EC 当前eden空间
EU eden空间使用
YGC young gc次数
YGCT 年轻代垃圾回收时间
-gcnewcapacity

内容与-gcnew基本相同,输出主要关注点使用到的最大、最小空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
jstat -gcnewcapacity 27087
NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC
1548288.0 1548288.0 1548288.0 154816.0 154816.0 154816.0 154816.0 1238656.0 1238656.0 24 5

---
NGCMN 年轻代最小容量
NGCMX 年轻代最大容量
NGC 当前年轻代容量
S0CMX S0最大空间
S0C S0当前空间
S1CMX S1最大空间
S1C S1当前空间
ECMX 最大eden空间
EC 当前eden空间
YGC young gc次数
FGC full gc次数
-gcold

显示老年代GC情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
jstat -gcold 27087
MC MU CCSC CCSU OC OU YGC FGC FGCT GCT
79812.0 77994.7 9928.0 9353.4 2572288.0 277280.1 24 5 0.339 4.037

---
MC 当前元空间容量
MU 元空间使用空间
CCSC 压缩类空间大小
CCSU 压缩类空间使用大小
OC 老年代大小
OU 老年代使用大小
YGC young gc次数
FGC full gc次数
FGCT full gc时间
GCT 垃圾收集总时间
-gcoldcapacity

内容与-gcold基本相同,输出主要关注使用到的最大、最小空间

1
2
3
4
5
6
7
8
9
10
11
12
13
jstat -gcoldcapacity 2713
OGCMN OGCMX OGC OC YGC FGC FGCT GCT
87552.0 1398272.0 87552.0 87552.0 0 0 0.000 0.000

---
OGCMN 老年代最小容量
OGCMX 老年代最大容量
OGC 当前老年代容量
OC 老年代容量
YGC young gc次数
FGC full gc次数
FGCT full gc时间
GCT 垃圾收集总时间
-printcompilation

输出最近被JIT编译的方法

1
2
3
4
5
6
7
8
9
jstat -printcompilation 27087
Compiled Size Type Method
15192 253 1 com/zhanghe/study/common/dao/TaskInstanceDaoImpl updateStarttime

---
Compiled 被执行的编译任务数量
Size 方法字节码的字节数
Type 编译的类
Method 编译的方法名

还可以每隔一段时间获取一次

1
2
# 1000表示1000ms,也就是1秒钟获取一次
jstat -printcompilation 27087 1000

jinfo命令

jinfo可以实时查看和修改jvm参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Usage:
jinfo [option] <pid>
(to connect to running process)
jinfo [option] <executable <core>
(to connect to a core file)
jinfo [option] [server_id@]<remote server IP or hostname>
(to connect to remote debug server)

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 开启或关闭对应的参数,只有被标记为manageable的参数可以被实时修改
-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 输出全部的参数和系统属性
-h | -help to print this help message

查看被标记为manageable的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
java -XX:+PrintFlagsFinal -version | grep manageable
intx CMSAbortablePrecleanWaitMillis = 100 {manageable}
intx CMSTriggerInterval = -1 {manageable}
intx CMSWaitDuration = 2000 {manageable}
bool HeapDumpAfterFullGC = false {manageable}
bool HeapDumpBeforeFullGC = false {manageable}
bool HeapDumpOnOutOfMemoryError = false {manageable}
ccstr HeapDumpPath = {manageable}
uintx MaxHeapFreeRatio = 100 {manageable}
uintx MinHeapFreeRatio = 0 {manageable}
bool PrintClassHistogram = false {manageable}
bool PrintClassHistogramAfterFullGC = false {manageable}
bool PrintClassHistogramBeforeFullGC = false {manageable}
bool PrintConcurrentLocks = false {manageable}
bool PrintGC = false {manageable}
bool PrintGCDateStamps = false {manageable}
bool PrintGCDetails = false {manageable}
bool PrintGCID = false {manageable}
bool PrintGCTimeStamps = false {manageable}

jmap命令

jmap命令可以导出内存映像文件(dump文件)以及内存使用情况,还可以查询finalize执行队列,java堆和永久代的详细信息,如空间使用率、当前用的哪种收集器等

生成dump文件比较耗时,尤其是大内存的则需要耗费更多的时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Usage:
jmap [option] <pid>
(to connect to running process)
jmap [option] <executable <core>
(to connect to a core file)
jmap [option] [server_id@]<remote server IP or hostname>
(to connect to remote debug server)

where <option> is one of:
<none> to print same info as Solaris pmap
-heap 输出整个堆空间的详细信息,包括使用哪种回收器、参数配置、分代状况等。
-histo[:live] pid查看堆内存中的对象数目、大小统计直方图,输出堆空间中对象的统计信息,包括类、实例数量和合计数量,如果加上live则只统计活对象
-clstats to print class loader statistics 以ClassLoader为统计口径输出内存状态信息
-finalizerinfo to print information on objects awaiting finalization 打印等待执行finalize方法的对象
-dump:<dump-options> to dump java heap in hprof binary format 生成dump文件
-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. 当虚拟机进程对-dump选项没有任何响应时,强制执行生成dump文件
-h | -help to print this help message
-J<flag> to pass <flag> directly to the runtime system 传递参数给jmap启动的jvm
统计存活对象情况
1
jmap -histo:live pid
导出dump文件

dump文件是堆存储文件,java进程在某个时间点的内存快照,保存的信息有所有的对象、所有的类、GC收集的根对象、线程栈以及局部变量表

可以手动的导出dump文件

1
2
# live表明只dump出存活的对象
jmap -dump:live,format=b,file=heap.bin <pid>

也可以自动的导出dump文件

设置JVM参数-XX:+HeapDumpOnOutOfMenmoryError-XX:HeapDumpPath=<file>

自动导出是由Full GC触发的,所以dump文件中保存的是Full GC后留下的对象信息

jhat命令

jhat是jdk中自带的堆分析工具,可以用来分析jmap生成的dump文件,jhat内置了一个小的HTTP服务器,生成dump文件的分析结果之后,可以在浏览器中查看分析结果,端口7000

不过一般不会使用jhat进行分析dump文件,而是使用VisualVM等相关工具进行分析

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
Usage:  jhat [-stack <bool>] [-refs <bool>] [-port <port>] [-baseline <file>] [-debug <int>] [-version] [-h|-help] <file>

-J<flag> Pass <flag> directly to the runtime system. For
example, -J-mx512m to use a maximum heap size of 512MB 传入启动参数
-stack false: Turn off tracking object allocation call stack. 关闭|打开对象分配调用栈跟踪
-refs false: Turn off tracking of references to objects 关闭|打开对象引用跟踪
-port <port>: Set the port for the HTTP server. Defaults to 7000 端口,默认7000
-exclude <file>: Specify a file that lists data members that should
be excluded from the reachableFrom query. 执行对象查询时需要排除的数据成员
-baseline <file>: Specify a baseline object dump. Objects in
both heap dumps with the same ID and same class will
be marked as not being "new". 制定一个基准堆转储文件
-debug <int>: Set debug level. 设置debug级别
0: No debug output
1: Debug hprof file parsing
2: Debug hprof file parsing, no server
-version Report version number 启动后显示版本信息就退出
-h|-help Print this help and exit
<file> The file to read

For a dump file that contains multiple heap dumps,
you may specify which dump in the file
by appending "#<number>" to the file name, i.e. "foo.hprof#3".

All boolean options default to "true"

jdk9时删除,使用VisualVM

jstack命令

jstack命令用来生成进程当前的线程堆栈快照,查看线程堆栈信息,当前虚拟机内每一条线程正在执行的方法堆栈的集合

可以用线程快照来定位线程出现长时间停顿的原因,如线程死锁、死循环、请求外部资源导致的长时间等待问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Usage:
jstack [-l] <pid>
(to connect to running process)
jstack -F [-m] [-l] <pid>
(to connect to a hung process)
jstack [-m] [-l] <executable> <core>
(to connect to a core file)
jstack [-m] [-l] [server_id@]<remote server IP or hostname>
(to connect to a remote debug server)

Options:
-F to force a thread dump. Use when jstack <pid> does not respond (process is hung) 当正常输出的请求不被响应时,强制输出线程堆栈
-m 可以输出java堆栈信息,如果调用到本地方法的话,可以显示C/C++的堆栈
-l long listing. 除堆栈外,显示关于锁的附加信息
-h or -help 打印帮助信息

在该dump中有如下几种状态

  • ※Deadlock 死锁
  • ※Waiting on condition 等待资源
  • ※Waiting on monitor entry 等待获取监视器
  • ※Blocked 阻塞
  • Runnable 执行中
  • Suspended 暂停
  • Object.wait()或TIMED_WAITING 对象等待中
  • Parked 停止

jcmd命令

jcmd命令集成了上述除stat之外的所有命令,是一个多功能的工具,可以用来导出堆、查看java进程、导出线程信息、执行GC等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Usage: jcmd <pid | main class> <command ...|PerfCounter.print|-f file>
or: jcmd -l
or: jcmd -h

command must be a valid jcmd command for the selected jvm.
Use the command "help" to see which commands are available.
If the pid is 0, commands will be sent to all Java processes.
The main class argument will be used to match (either partially
or fully) the class used to start Java.
If no options are given, lists Java processes (same as -p).

PerfCounter.print display the counters exposed by this process
-f read and execute commands from the file
-l list JVM processes on the local machine 列出所有的JVM线程
-h this help

对于具体的进程进行操作

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
jcmd 2713 help
2713:
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 导出堆信息,后跟存储到的文件位置 如 jcmd 11231 GC.heap_dump /path/to/heap_dump.hprof,默认是存活的对象,如果想包含所有对象,则在最后加上-all
GC.finalizer_info
GC.heap_info
GC.run_finalization
GC.run 进行GC
VM.uptime 查看虚拟机启动时间
VM.dynlibs
VM.flags 获取启动设置的参数,如果使用 VM.flags -all 可以获取JVM内部所有的参数
VM.system_properties 获取系统properties
VM.command_line JVM命令行
VM.version JVM版本
help

打印出来的堆栈信息

1
2
"resin-47"(线程名称) #47 daemon prio=5(线程优先级) os_prio=31 tid=0x00007ffb9080e000(线程id) nid=0x7a03(线程对应的本地线程id) waiting on condition (线程状态)[0x000070000674d000](线程占用的内存地址)
java.lang.Thread.State: WAITING (parking)

可视化工具

VisualVM

用于查看java应用程序的详细信息,可以显示虚拟机进程及进程的配置和环境信息(jps,jinfo),监视应用程序的CPU、GC/堆、方法区及线程的信息(jstat、jstack),使用jvisualvm命令

概述

可以查看应用的基本情况,如进程ID、主类、启动参数等

VisualVM概览

监视

可以监控CPU、永久区、类加载和线程,点击执行垃圾回收可以触发Full GC,点击堆Dump可以生成堆快照

VisualVM监视

线程

VisualVM线程

抽样器

Visual VM有两个抽样器,CPU和内存

VisualVM抽样器

远程连接

如果需要使用VisualVM进行远程连接,需要在启动的java程序加上如下参数

1
2
3
4
5
-Djava.rmi.server.hostname=127.0.0.1
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8888
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

这样在使用VisualVM进行JMX连接时使用 127.0.0.1:8888访问

Jconsole

JDK自带的可视化监控工具,可以查看java应用程序的运行概况、监控堆信息、元空间使用情况、类加载情况等,基于JMX的GUI性能监控工具,使用jconsole命令

启动Jconsole后会自动搜索本机运行的所有虚拟机进程

概览

可以显示堆内存的使用量、系统线程数量、加载类数量以及cpu使用率

JConsole概览

内存

可以看到堆内存以及细化到各个区的内存,点击执行GC可以强制触发一次Full GC

JConsole内存

线程

可以展示程序中的所有线程

JConsole线程

类加载

显示系统装载的类数量

JConsole类加载

虚拟机信息

可以展示当前程序应用的运行环境,包括虚拟机类型、版本、系统线程信息、堆信息、垃圾回收器类型、操作系统信息以及虚拟机参数等

JConsole虚拟机概要

远程连接

如果需要使用jconsole进行远程连接,需要在启动的java程序加上如下参数

1
2
3
4
5
-Djava.rmi.server.hostname=127.0.0.1
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8888
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

这样在使用jconsole进行远程连接时使用 127.0.0.1:8888访问

btrace

java运行时追踪工具,可以在不停机的情况下,追踪指定方法的调用、构造函数调用和系统内存等信息,相当于进行切面处理

1
2
3
4
5
6
7
8
btrace [-I <include-path>] [-p <port>] [-cp <classpath>] <pid> <btrace-script> [<args>]
-I BTrace支持对#define、#include这样的条件编译指令进行简单的处理,include-path用来指
定这样的头文件目录
-p port参数用来指定btrace agent端口,默认是2020
-cp classpath用来指定编译所需类路径,一般是指btrace-client.jar等类所在路径
pid 表示需要跟踪的java进程id
btrace-script 为自定义的 btrace脚本
args 为传递给btrace脚本的参数

JMC

内置Java Flight Recorder,用来收集JVM的性能数据

MAT

MAT(Memory Analyzer Tool)基于Eclipse的内存分析工具,查找内存泄漏等问题,是Eclipse的插件

我在mac本上单独使用mat时报错,

java.lang.IllegalStateException: The platform metadata area could not be written: /private/var/folders/gn/d0l73l5d5wgdqc30m1pjkqp40000gn/T/AppTranslocation/B22F2288-7772-4327-9973-D41F1D0B2B7B/d/mat.app/Contents/MacOS/workspace/.metadata. By default the platform writes its content
under the current working directory when the platform is launched. Use the -data parameter to
specify a different content area for the platform

可以右键mat显示包内容,进入Contents->MacOS下面,会有一个MemoryAnalyzer的命令。
打开终端,进入此路径找到MemoryAnalyzer,运行./MemoryAnalyzer -data dump文件所在文件夹路径

Jprofiler

与VisualVM类似,商业付费

Arthas

阿里开源的java诊断工具,在线排查问题,无需重启;动态跟踪java代码;实时监控JVM状态

官网地址:https://arthas.aliyun.com/zh-cn/ 中文的呦,看着比较省事

GCViewer

离线GC日志分析工具

GC Easy

在线GC日志分析工具 https://gceasy.io/

欢迎关注我的其它发布渠道