JDK分析工具及调优

一、JDK分析工具

JVM常用分析工具

JDK的bin目录中有“java.exe”、 “javac.exe”这两个命令行工具,但bin目录之中还有很多其他命令行程序,这些工具非常强大可以用于监视虚拟机和故障处理。

工具名称作用描述
jps.exeJVM进程状态工具(JVM Process Status Tool),用于显示目标系统上JVM的Java进程信息
jstat.exeJVM统计监测工具(JVM Statistics Monitoring Tool),主要用于监测并显示JVM的性能统计信息
jinfo.exeJava配置信息工具(Java Configuration Information),用于打印指定Java进程、核心文件或远程调试服务器的配置信息
jhat.exeJava堆分析工具(Java Heap Analysis Tool),用于分析Java堆内存中的对象信息
jmap.exeJava内存映射工具(Java Memory Map),主要用于打印指定Java进程、核心文件或远程调试服务器的共享对象内存映射或堆内存细节
jstack.exeJava堆栈跟踪工具,主要用于打印指定Java进程、核心文件或远程调试服务器的Java线程的堆栈跟踪信息
jmc.exeJava任务控制工具(Java Mission Control),主要用于JVM的生产时间监测、分析、诊断
jvisualvm.exeJVM监测、故障排除、分析工具,主要以图形化界面的方式提供运行于指定虚拟机的Java应用程序的详细信息
jconsole.exe图形化用户界面的监测工具,主要用于监测并显示运行于Java平台上的应用程序的性能和资源占用等信息
## jps 显示正在运行的虚拟机进程
$ 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

显示标头含义:

Bytesclass字节大小
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大小
EEden区使用比例
EC当前Eden空间
EUEden区的使用大小
ECMX最大Eden区空间
TT对象在新生代存活的次数Tenuring threshold(提升阈值)
MTT对象在新生代存活的最大次数,最大的tenuring threshold
DSS期望的幸存区大小,survivor区域大小 (KB)
PCPerm大小(JDK1.8之前)
PUPerm使用大小(JDK1.8之前)
PGCMNPerm占用的最小空间(JDK1.8之前)
PGCMXPerm占用的最大空间(JDK1.8之前)
PGCPerm空间 (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

线程状态

  1. 死锁, Deadlock(重点关注)
  2. 等待资源, Waiting on condition(重点关注)
  3. 等待获取监视器, Waiting on monitor entry(重点关注)
  4. 阻塞, Blocked(重点关注)
  5. 执行中,Runnable
  6. 暂停,Suspended
  7. 对象等待中,Object.wait() 或 TIMED_WAITING
  8. 停止,Parked

Waiting on condition
该状态出现在线程等待某个条件的发生。具体是什么原因,可以结合 stacktrace来分析。如果发现有大量的线程都在处在 Wait on condition,从线程 stack看, 正等待网络读写,这可能是一个网络瓶颈的征兆。因为网络阻塞导致线程无法执行。一种情况是网络非常忙,几 乎消耗了所有的带宽,仍然有大量数据等待网络读 写;另一种情况也可能是网络空闲,但由于路由等问题,导致包无法正常的到达。

Waiting for monitor entry 和 in Object.wait()
Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象有也仅有一个 monitor。

初始化线程

  1. main
    主线程,用于执行我们编写的Java程序的main方法
  2. Reference Handler
    处理引用的线程。它主要用于处理引用对象本身(软引用、弱引用、虚引用)的垃圾回收问题。
  3. Finalizer
    调用对象的finalize方法的线程,就是垃圾回收的线程。JVM在垃圾收集时会将失去引用的对象包装成Finalizer对象(Reference的实现),并放入ReferenceQueue,由Finalizer线程来处理;最后将该Finalizer对象的引用置为null,由垃圾收集器来回收
  4. Attach Listener
    负责接收外部的命令的线程。该线程是负责接收到外部的命令,执行该命令,并且把结果返回给发送者。通常我们会用一些命令去要求JVM给我们一些反馈信息,如:java -version、jmap、 jstack等等。如果该线程在JVM启动的时候没有初始化,那么,则会在用户第一次执行JVM命令时,得到启动
  5. 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。该参数的形式分为两大类:

  1. Boolean型
    格式:-XX:[+|-] 表示启用或者禁用name属性。
    例如:-XX:+UseSerialGC
  2. *Key-Value类型
    格式:-XX:= 表示name的属性值为value。
    例如:-XX:MaxTenuringThreshold=15

实现调优

调优的原则

  1. 合理编写代码
  2. 合理利用硬件资源
  3. 合理地进行调优
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值