JVM学习笔记(十一、JDK分析工具)
目录:
- JVM常用工具分析
- jps
- jstat
- jmap
- jstack
- jconsole
- jvisualvm
JVM常用工具分析
JDK bin目录下中我们所熟知的工具有java.ext、javac.ext,但还有一些其它的命令行程序,可用于监视虚拟机和故障处理。
工具名称 | 作用描述 |
jps.exe | JVM进程状态工具(JVM Process Status Tool),用于显示目标系统上JVM的Java进程信息。 |
jstat.exe | JVM统计监测工具(JVM Statistics Monitoring Tool),主要用于监测并显示JVM的性能统计信息。 |
jinfo.exe | Java配置信息工具(Java Configuration Information),用于打印指定Java进程、核心文件或远程调试服务器的配置信息。 |
jhat.exe | Java堆分析工具(Java Heap Analysis Tool),用于分析Java堆内存中的对象信息。 |
jmap.exe | Java内存映射工具(Java Memory Map),主要用于打印指定Java进程、核心文件或远程调试服务器的共享对象内存映射或堆内存细节。 |
jstack.exe | Java堆栈跟踪工具,主要用于打印指定Java进程、核心文件或远程调试服务器的Java线程的堆栈跟踪信息。 |
jmc.exe | Java任务控制工具(Java Mission Control),主要用于JVM的生产时间监测、分析、诊断。 |
jvisualvm.exe | JVM监测、故障排除、分析工具,主要以图形化界面的方式提供运行于指定虚拟机的Java应用程序的详细信息。 |
jconsole.exe | 图形化用户界面的监测工具,主要用于监测并显示运行于Java平台上的应用程序的性能和资源占用等信息。 |
jps:jps [-q] [-mlv] [<hostid>]
显示正在运行的虚拟机进程,不带参数显示全部JVM进程,指定hostid仅展示指定的进程信息。
- -q:只显示LVMID,省略主类信息(LVMID:本地虚拟机进程唯一编号)。
- -l:显示虚拟机启动进程时传递给main()的参数。
- -m:显示类全面,如果是jar包显示jar路径。
- -v:显示虚拟机启动时候的JVM参数。
jstat:
显示本地或者远程虚拟机进程中的类装载、 内存、 垃圾收集、 JIT编译等运行数据,是定位虚拟机性能问题的首选工具。
该命令有多个常用参数:
-class |
类加载数量、卸载数量、总空间及类装载所耗费的时间。 |
-compiler |
显示JIT编译器编译过的方法、耗时等信息。 |
-gc |
统计Java堆,包括Eden、Survivor、老年代、永久代的容量,已用空间、GC时间等信息。 |
-gccapacity |
显示Java堆各个区域使用到的最大、最小空间。 |
-gcutil |
显示已使用空间占总空间的百分比。 |
-gccause |
垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的原因。 |
-gcnew |
新生代行为统计。 |
-gcnewcapacity |
新生代使用到的最大、最小空间统计。 |
-gcold |
统计老年代GC状况。 |
-gcoldcapacity |
年老代行为统计(同-gcoldcapacity),主要关注使用到的最大、最小空间。 |
-gcpermcapacity |
显示永久代使用到的最大、最小空间(-gcmetacapacity)。 |
-printcompilation |
显示已经被JIT编译的方法。 |
1、class:监视类装载、卸载数量、总空间以及耗费的时间。
表头信息:
- Bytes:class字节大小。
- Unloaded:未加载class的数量。
- Bytes:未加载class的字节大小。
- Time:加载时间。
2、compiler:输出JIT编译过的方法数量耗时等。
表头信息:
- Failed:编译失败数量。
- Invalid:无效数量。
- Time:编译耗时。
- FailedType:失败类型。
- FailedMethod:失败方法的全限定名。
3、gc:垃圾回收堆的行为统计。
4、gccapacity:同-gc,还会输出Java堆各区域使用到的最大、最小空间。
5、gcutil:同-gc,输出的是已使用空间占总空间的百分比。
6、gccause:垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的原因。
7、gcnew:统计新生代行为信息。
8、gcnewcapacity:新生代与其相应的内存空间的统计。
9、gcold:统计老年代行为。
10、gcoldcapacity:老年代与其相应的内存空间的统计。
11、gcpermcapacity:永久代与其相应内存空间的统计(JDK 1.8及之后的版本,该参数位-gcmetacapacity)。
12、printcompilation:显示hotspot编译方法统计。
表头说明:
- Compiled:最近编译方法的数量。
- Type:最近编译方法的编译类型。
- Size:最近编译方法的字节码数。
- Method:编译方法的类名和方法名。类名使用"/" 代替 "." 作为空间分隔符。方法名是给出类的方法名。格式和HotSpot - XX:+PrintComplation 选项一致。
jstat英文标头释义:
英文标头: |
含义: |
NGC |
当前新生代容量 (KB)。 |
NGCMN |
新生代最小容量。 |
NGCMX |
新生代最大容量。 |
S0 |
幸存区S0当前使用比例。 |
S0C |
当前幸存区S0空间 (KB)。 |
S0U |
第一个幸存区的使用大小。 |
S0CMX |
最大幸存区S0大小 (KB)。 |
S1 |
幸存区S1当前使用比例。 |
S1C |
当前幸存区S1大小。 |
S1U |
第二个幸存区的使用大小。 |
S1CMX |
最大幸存区S1大小。 |
E |
Eden区使用比例。 |
EC |
当前Eden空间 (KB)。 |
EU |
Eden区的使用大小。 |
ECMX |
最大Eden区空间 (KB)。 |
TT |
对象在新生代存活的次数Tenuring threshold(提升阈值)。 |
MTT |
对象在新生代存活的最大次数,最大的tenuring threshold。 |
DSS |
期望的幸存区大小,survivor区域大小 (KB)。 |
PC |
Perm大小(JDK1.8之前)。 |
PU |
Perm使用大小(JDK1.8之前)。 |
PGCMN |
Perm占用的最小空间(JDK1.8之前)。 |
PGCMX |
Perm占用的最大空间(JDK1.8之前)。 |
PGC |
Perm空间 (KB)(JDK1.8之前)。 |
M |
元数据区使用比例(JDK1.8之后)。 |
MC |
方法区大小(JDK1.8之后)。 |
MU |
方法区使用大小(JDK1.8之后)。 |
MCMN |
最小元数据容量(JDK1.8之后)。 |
MCMX |
最大元数据容量(JDK1.8之后)。 |
O |
老年代使用比例。 |
OC |
当前年老代的空间 (KB)。 |
OU |
老年代使用大小。 |
OGC |
当前年老代的容量 (KB)。 |
OGCMN |
老年代最小容量。 |
OGCMX |
老年代最大容量。 |
CCS |
压缩使用比例(JDK1.8之后)。 |
CCSC |
压缩类空间大小(JDK1.8之后)。 |
CCSU |
压缩类空间使用大小(JDK1.8之后)。 |
CCSMN |
最小压缩类空间大小(JDK1.8之后)。 |
CCSMX |
最大压缩类空间大小(JDK1.8之后)。 |
YGC |
年轻代垃圾回收次数。 |
YGCT |
年轻代垃圾回收消耗时间。 |
FGC |
老年代垃圾回收次数。 |
FGCT |
老年代垃圾回收消耗时间。 |
GCT |
垃圾回收消耗总时间。 |
jmap:
用于生成heap dump文件,如果不使用这个命令,还可以使用-XX:+HeapDumpOnOutOfMemoryError参数来让虚拟机出现OOM的时候自动生成dump文件。
jmap不仅能生成dump文件,还可以查询finalize执行队列、Java堆和永久代的详细信息,如当前使用率、当前使用的是哪种收集器等。
1 # 显示堆中对象的统计信息,包括类、有多少个实例,合计容量等 2 $ jmap -histo hostip 3 $ jmap -histo:live hostip 4 5 # 生成Java堆快照。格式:-dump:[live, ]format=b, file=<filename> 6 # live为是否只生成存活的对象 7 $ jmap -dump:file=hostip.hprof 8 9 # 显示堆详细信息,如使用哪种回收器、参数配置、分代状况等 10 $ jmap -heap hostip 11 12 # 打印类加载统计信息 13 $ jmap -clstats hostip 14 15 # 显示在F-Queue中等待Finalizer线程执行finalize方法的对象 16 $ jmap -finalizerinfo hostip
MAT:
MAT(Eclipse Memory Analyzer Tool)是一种快速且功能丰富的Java堆分析器,可帮助你查找内存泄漏并减少内存消耗。
使用MAT可以分析包含数亿个对象的高效堆转储,快速计算对象的大小,查看阻止垃圾收集器收集对象的原因,运行报告并自动提取可疑泄漏。
当我们需要处理hprof文件对象转储文件,分析内存相关问题时,MAT绝对是不二之选。
MAT可以作为一个独立分析工具使用,也可以通过Eclipse下载插件结合使用。
jstack:
用于生成虚拟机当前时刻的线程快照,以便可以进一步定位线程出现长时间停顿的原因,如线程间死锁、 死循环、 请求外部资源导致的长时间等待等。
显示结果信息:
- prio线程的优先级。
- tid线程id。
- nid操作系统映射的线程id。
1、线程状态:
- 死锁,Deadlock(重点关注)。
- 执行中,Runnable。
- 等待资源,Waiting on condition(重点关注)。
- 等待获取监视器,Waiting on monitor entry(重点关注)。
- 暂停,Suspended。
- 对象等待中,Object.wait() 或 TIMED_WAITING。
- 阻塞,Blocked(重点关注)。
- 停止,Parked。
2、Waiting on condition:
该状态出现在线程等待某个条件的发生,具体是什么原因,可以结合 stacktrace来分析。
如果发现有大量的线程都在处在 Wait on condition,从线程 stack看, 正等待网络读写,这可能是一个网络瓶颈的征兆。
因为网络阻塞导致线程无法执行,一种情况是网络非常忙,几 乎消耗了所有的带宽,仍然有大量数据等待网络读 写;
另一种情况也可能是网络空闲,但由于路由等问题,导致包无法正常的到达。
3、Waiting for monitor entry 和 in Object.wait():
Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁,每一个对象有也仅有一个 monitor。
4、初始化线程:
- main:主线程,用于执行我们编写的Java程序的main方法。
- Reference Handler:处理引用的线程。它主要用于处理引用对象本身(软引用、弱引用、虚引用)的垃圾回收问题。
- Finalizer:调用对象的finalize方法的线程,就是垃圾回收的线程。
- JVM在垃圾收集时会将失去引用的对象包装成Finalizer对象(Reference的实现),并放入ReferenceQueue,由Finalizer线程来处理;
- 最后将该Finalizer对象的引用置为null,由垃圾收集器来回收。
- Attach Listener:负责接收外部的命令的线程。
- 该线程是负责接收到外部的命令,执行该命令,并且把结果返回给发送者。
- 通常我们会用一些命令去要求JVM给我们一些反馈信息,如:java -version、jmap、 jstack等等。如果该线程在JVM启动的时候没有初始化,那么,则会在用户第一次执行JVM命令时,得到启动。
- Signal Dispatcher:分发处理发送给JVM信号的线程。
- 前面我们提到第一个Attach Listener线程的职责是接收外部JVM命令,当命令接收成功后,会交给signal dispather线程去进行分发到各个不同的模块处理命令,并且返回处理结果。
- signal dispather线程也是在第一次接收外部JVM命令时,进行初始化工作。
jconsole:
JDK自带的集多种分析于一体的可视化图形工具。
jvisualvm:
JDK自带的集多种分析于一体的可视化图形工具,并可以下载多种插件扩展其监控分析功能。