概述
一、JDK分析工具
JVM常用分析工具
JDK的bin目录中有“java.exe”、 “javac.exe”这两个命令行工具,但bin目录之中还有很多其他命令行程序,这些工具非常强大可以用于监视虚拟机和故障处理。
工具名称 | 作用描述 |
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 4562
可选参数:
- -q 只显示LVMID,省略主类信息(LVMID:本地虚拟机进程唯一编号)
- -l 显示虚拟机启动进程时传递给main()的参数
- -m 显示类全面,如果是jar包显示jar路径
- -v 显示虚拟机启动时候的JVM参数
jstat
显示本地或者远程虚拟机进程中的类装载、 内存、 垃圾收集、 JIT编译等运行数据。是定位虚拟机性能问题的首选工具。该命令有多个常用参数:
命令选项 | 描述 |
-class | 类加载、卸载数量、总空间及类装载所耗费的时间 |
-compiler | 显示JIT编译器编译过的方法、耗时等信息 |
-gc | 统计Java堆,包括Eden、Survivor、老年代、永久代的容量,已用空间、GC时间等信息 |
-gccapacity | 显示Java堆各个区域使用到的最大、最小空间 |
-gccause | 垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的原因 |
-gcnew | 新生代行为统计 |
-gcnewcapacity | 新生代使用到的最大、最小空间统计 |
-gcold | 统计老年代GC状况 |
-gcoldcapacity | 年老代行为统计(同-gcoldcapacity),主要关注使用到的最大、最小空间 |
-gcpermcapacity | 显示永久代使用到的最大、最小空间(-gcmetacapacity) |
-printcompilation | 显示已经被JIT编译的方法 |
class
监视类装载、卸载数量、总空间以及耗费的时间
$ jstat -class 4562
显示标头含义:
Bytes | class字节大小 |
Unloaded | 未加载class的数量 |
Bytes | 未加载class的字节大小 |
Time | 加载时间 |
compiler
输出JIT编译过的方法数量耗时等
$ jstat -compiler 4562
显示标头含义:
Failed | 编译失败数量 |
Invalid | 无效数量 |
Time | 编译耗时 |
FailedType | 失败类型 |
FailedMethod | 失败方法的全限定名 |
gc
垃圾回收堆的行为统计
$ jstat -gc 4562
gccapacity
同-gc,还会输出Java堆各区域使用到的最大、最小空间
$ jstat -gccapacity 4562
gcutil
同-gc,输出的是已使用空间占总空间的百分比
$ jstat -gcutil 4562
gccause
垃圾收集统计概述(同-gcutil),附加最近两次垃圾回收事件的原因
$ jstat -gccause 4562
gcnew
$ jstat -gcnew 4562
gcnewcapacity
新生代与其相应的内存空间的统计
$ jstat -gcnewcapacity 4562
gcold
统计老年代行为
$ jstat -gcold 4562
gcoldcapacity
老年代与其相应的内存空间的统计
$ jstat -gcoldcapacity 4562
gcpermcapacity
永久代与其相应内存空间的统计。
$ jstat -gcnewcapacity 4562
JDK 1.8及之后的版本,该参数位-gcmetacapacity
printcompilation
显示hotspot编译方法统计
jstat -gcnewcapacity 4562
显示标头含义:
Compiled | 最近编译方法的数量 |
Type | 最近编译方法的编译类型 |
Size | 最近编译方法的字节码数 |
Method | 编译方法的类名和方法名。类名使用"/" 代替 "." 作为空间分隔符。方法名是给出类的方法名。格式和HotSpot - XX:+PrintComplation 选项一致 |
jstat英文标头释义
英文标头 | 含义 |
NGC | 当前新生代容量 (KB) |
NGCMN | 新生代最小容量 |
NGCMX | 新生代最大容量 |
S0 | 幸存区S0当前使用比例 |
S0C | 当前幸存区S0空间 |
S0U | 第一个幸存区的使用大小 |
S0CMX | 最大幸存区S0大小 |
S1 | 幸存区S1当前使用比例 |
S1C | 当前幸存区S1大小 |
S1U | 第二个幸存区的使用大小 |
S1CMX | 最大幸存区S1大小 |
E | Eden区使用比例 |
EC | 当前Eden空间 |
EU | Eden区的使用大小 |
ECMX | 最大Eden区空间 |
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 | 当前年老代的空间 |
OU | 老年代使用大小 |
OGC | 当前年老代的容量 |
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堆和永久代的详细信息,如当前使用率、当前使用的是哪种收集器等。
# 显示堆中对象的统计信息,包括类、有多少个实例,合计容量等
$ jmap -histo 4562
$ jmap -histo:live 4562
# 生成Java堆快照。格式:-dump:[live, ]format=b, file=<filename>
# live为是否只生成存活的对象
$ jmap -dump:file=4562.hprof
# 显示堆详细信息,如使用哪种回收器、参数配置、分代状况等
$ jmap -heap 4562
# 打印类加载统计信息
$ jmap -clstats 4562
# 显示在F-Queue中等待Finalizer线程执行finalize方法的对象
$ jmap -finalizerinfo 4562
MAT
MAT(Eclipse Memory Analyzer Tool)是一种快速且功能丰富的Java堆分析器,可帮助你查找内存泄漏并减少内存消耗。 使用MAT可以分析包含数亿个对象的高效堆转储,快速计算对象的大小,查看阻止垃圾收集器收集对象的原因,运行报告并自动提取可疑泄漏。
当我们需要处理hprof文件对象转储文件,分析内存相关问题时,MAT绝对是不二之选。 MAT可以作为一个独立分析工具使用,也可以通过Eclipse下载插件结合使用。
项目主页:https://www.eclipse.org/mat/
https://projects.eclipse.org/projects/tools.mat
使用入门:https://wiki.eclipse.org/MemoryAnalyzer
参考文档:https://help.eclipse.org/2019-12/index.jsp?topic=/org.eclipse.mat.ui.help/welcome.html
下载地址:https://www.eclipse.org/mat/downloads.php
jstack
用于生成虚拟机当前时刻的线程快照,以便可以进一步定位线程出现长时间停顿的原因,如线程间死锁、 死循环、 请求外部资源导致的长时间等待等
$ jstack 4562
显示标头含义:
prio | 线程的优先级 |
tid | 线程id |
nid | 操作系统映射的线程id |
线程状态
- 死锁, Deadlock(重点关注)
- 等待资源, Waiting on condition(重点关注)
- 等待获取监视器, Waiting on monitor entry(重点关注)
- 阻塞, Blocked(重点关注)
- 执行中,Runnable
- 暂停,Suspended
- 对象等待中,Object.wait() 或 TIMED_WAITING
- 停止,Parked
Waiting on condition
该状态出现在线程等待某个条件的发生。具体是什么原因,可以结合 stacktrace来分析。如果发现有大量的线程都在处在 Wait on condition,从线程 stack看, 正等待网络读写,这可能是一个网络瓶颈的征兆。因为网络阻塞导致线程无法执行。一种情况是网络非常忙,几 乎消耗了所有的带宽,仍然有大量数据等待网络读 写;另一种情况也可能是网络空闲,但由于路由等问题,导致包无法正常的到达。
Waiting for monitor entry 和 in Object.wait()
Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象有也仅有一个 monitor。
初始化线程
- 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自带的集多种分析于一体的可视化图形工具,并可以下载多种插件扩展其监控分析功能。
插件中心地址:https://visualvm.github.io/pluginscenters.html
二、JVM实战调优
JVM参数形式
标准参数
标准参数中包括功能以及输出的结果很稳定,基本上不会随着JVM版本的变化而变化。可以通过-help 命令查看所有标准参数。
$ java -help
X参数
非标准化参数。在将来的JVM版本中可能会发生改变,但是这类以-X开始的参数变化的比较小。可以通过 Java -X 命令查看所有-X 参数
$ java -X
XX参数
非标准化参数。相对来说不稳定,随着JVM版本的变化可能会发生变化,主要用于JVM调优和debug。该参数的形式分为两大类:
- Boolean型
格式:-XX:[+|-] 表示启用或者禁用name属性。
例如:-XX:+UseSerialGC - *Key-Value类型
格式:-XX:= 表示name的属性值为value。
例如:-XX:MaxTenuringThreshold=15
实现调优
调优的原则
- 合理编写代码
- 合理利用硬件资源
- 合理地进行调优
最后
以上就是爱听歌钢笔为你收集整理的JDK分析工具及调优一、JDK分析工具二、JVM实战调优的全部内容,希望文章能够帮你解决JDK分析工具及调优一、JDK分析工具二、JVM实战调优所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复