一、JDK 监控工具1.1 jps: jvm进程状况工具
显示指定系统内的所有HotSpot进程,命令格式:
jps [option] [ hostid]
hostid为RMI注册表中注册的主机名

image.png

1.2 jstat:jvm统计信息监视工具
用于收集HotSpot个方面的运行数据,包括类装载、内存、垃圾回收、JIT等运行数据,在没有GUI界面,它将是jvm性能问题的首选项。

jstat [option vmid [interval[m|ms] [count] ] ]

如果是远程程序 vmid变成 [protocal:][//]vmid[@hostname[:port]/servername]

Option主要分为三类:1.类装载;2垃圾回收;3.运行期编译状况。

image.png
C:\Program Files\Java\jdk1.8.0_181\bin>jstat -gc 15800 S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
5120.0 5120.0 0.0 5097.8 33280.0 17026.3 87552.0 754.3 20992.0 20348.8 2560.0 2367.3 3 0.026 0 0.000 0.026

1.3 jinfo: java配置信息工具
jinfo -flags 2289 查看启动参数
显示jvm配置信息,+或- 配置jvm参数

1.4 jmap:java内存映象工具
用于生成堆转储快照,还可以参看finalize执行队列,java堆、永久代的详情,如空间使用率,哪种垃圾回收器等。

image.png

jmap -dump:format=b,file=heap.hprof 31531
获得堆快照文件之后,我们可以使用多种工具对文件进行分析,例如jhat,visual vm等。

1.5 jhat:jvm堆转储快照分析工具
使用jhat工具可以分析Java应用程序的堆快照文件,使用命令如下:
jhat heap.hprof

jhat在分析完成之后,使用HTTP服务器展示其分析结果,在浏览器中访问http://127.0.0.1:7000/即可得到分析结果。

1.6 jstack : java堆栈跟踪工具
用于生成kvm当前线程的快照(threadtump或javacore工具)

image.png
1.7 HSDIS: JIT代码生成反汇编
让HotSpot的-XX:+printAssembly指令调用它来把动态代码生成的本地代码还原成汇编输出。

1.8 jstatd命令
jstatd命令是一个RMI服务器程序,它的作用相当于代理服务器,建立本地计算机与远程监控工具的通信,jstatd服务器能够将本机的Java应用程序信息传递到远程计算机,由于需要多台计算机做演示,此处略。

1.9 hprof工具
hprof工具可以用于监控Java应用程序在运行时的CPU信息和堆信息,关于hprof的官方文档如下:https://docs.oracle.com/javase/7/docs/technotes/samples/hprof.html

2 jdk可视化工具
2.1 jconsole
2.2 VisualVM
2.3 MAT内存分析工具
MAT是一款功能强大的Java堆内存分析器,可以用于查找内存泄露以及查看内存消耗情况,MAT的官方文档如下:http://help.eclipse.org/luna/index.jsp?topic=/org.eclipse.mat.ui.help/welcome.html

在MAT中有浅堆和深堆的概念,浅堆是指一个对象结构所占用的内存大小,深堆是指一个对象被GC回收后可以真正释放的内存大小。

通过MAT,可以列出所有垃圾回收的根对象,Java系统的根对象可能是以下类:系统类,线程,Java局部变量,本地栈等等。在MAT中还可以很清楚的看到根对象到当前对象的引用关系链。

MAT还可以自动检测内存泄露,单击菜单上的Leak Suspects命令,MAT会自动生成一份报告,这份报告罗列了系统内可能存在内存泄露的问题点。

在MAT中,还可以自动查找并显示消耗内存最多的几个对象,这些消耗大量内存的大对象往往是解决系统性能问题的关键所在。

  1. Arthas - Java
    官网:https://alibaba.github.io/arthas
    强大功能:

是否有一个全局视角来查看系统的运行状况?
为什么 CPU 又升高了,到底是哪里占用了 CPU ? 运行的多线程有死锁吗?有阻塞吗?
程序运行耗时很长,是哪里耗时比较长呢?如何监测呢?
这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
有什么办法可以监控到 JVM 的实时运行状态?
3.1 下载与启动:
arthas-boot.jar,然后用java -jar的方式启动:

运行方式1,先运行,在选择 Java 进程 PIDjava -jar arthas-boot.jar
# 选择进程(输入[]内编号(不是PID)回车)
[INFO] arthas-boot version: 3.1.4
[INFO] Found existing java process, please choose one and hit RETURN.
* [1]: 11616 com.Arthas
[2]: 8676
[3]: 16200 org.jetbrains.jps.cmdline.Launcher
[4]: 21032 org.jetbrains.idea.maven.server.RemoteMavenServer
# 运行方式2,运行时选择 Java 进程 PID
java -jar arthas-boot.jar [PID]
3.2 常用命令
image.png
3.2.1 全局监控
使用 dashboard 命令可以概览程序的 线程、内存、GC、运行环境信息。

image.png

3.2.2 CPU 高
使用 thread查看所有线程信息,同时会列出每个线程的 CPU 使用率,可以看到图里 ID 为12 的线程 CPU 使用100%。
image.png

使用命令 thread 12 查看 CPU 消耗较高的 12 号线程信息,可以看到 CPU 使用较高的方法和行数
image.png
上面是先通过观察总体的线程信息,然后查看具体的线程运行情况。如果只是为了寻找 CPU 使用较高的线程,可以直接使用命令 thread -n [显示的线程个数] ,就可以排列出 CPU 使用率 Top N 的线程。
image.png

3.2.3 线程池线程状态
使用 thread | grep pool 命令查看线程池里线程信息。

image.png

3.2.4 线程死锁检测
使用 thread -b 命令查看直接定位到死锁信息。

image.png

3.2.5 反编译
如果怀疑不是自己的代码,可以使用 jad 命令直接反编译 class。
image.png

jad 命令还提供了一些其他参数:

反编译只显示源码
jad —source-only com.Arthas
# 反编译某个类的某个方法
jad —source-only com.Arthas mysql
3.2.6 查看字段信息
使用 sc -d -f 命令查看类的字段信息。

[arthas@20252]$ sc -d -f com.Arthas
sc -d -f com.Arthas
class-info com.Arthas
code-source /C:/Users/Niu/Desktop/arthas/target/classes/
name com.Arthas
isInterface false
isAnnotation false
isEnum false
isAnonymousClass false
isArray false
isLocalClass false
isMemberClass false
isPrimitive false
isSynthetic false
simple-name Arthas
modifier public
annotation
interfaces
super-class +-java.lang.Object
class-loader +-sun.misc.Launcher$AppClassLoader@18b4aac2
+-sun.misc.Launcher$ExtClassLoader@2ef1e4fa
classLoaderHash 18b4aac2
fields modifierfinal,private,static
type org.slf4j.Logger
name log
value Logger[com.Arthas]

  1. modifierprivate,static<br /> type java.util.HashSet<br /> name hashSet<br /> value [count1, count2]
  2. modifierprivate,static<br /> type java.util.concurrent.ExecutorService<br /> name executorService<br /> value java.util.concurrent.ThreadPoolExecutor@71c03156[Ru<br /> nning, pool size = 1, active threads = 1, queued ta<br /> sks = 0, completed tasks = 0]

Affect(row-cnt:1) cost in 9 ms.

3.2.7 查看方法信息
使用 sm 命令查看类的方法信息。

[arthas@22180]$ sm com.Arthas
com.Arthas ()V
com.Arthas start()V
com.Arthas thread()V
com.Arthas deadThread()V
com.Arthas lambda$cpuHigh$1()V
com.Arthas cpuHigh()V
com.Arthas lambda$thread$3()V
com.Arthas addHashSetThread()V
com.Arthas cpuNormal()V
com.Arthas cpu()V
com.Arthas lambda$addHashSetThread$0()V
com.Arthas lambda$deadThread$4(Ljava/lang/Object;Ljava/lang/Object;)V
com.Arthas lambda$deadThread$5(Ljava/lang/Object;Ljava/lang/Object;)V
com.Arthas lambda$cpuNormal$2()V
Affect(row-cnt:16) cost in 6 ms.

3.2.8 查看变量的值
使用 ognl 命令,ognl 表达式可以轻松操作想要的信息。

查看静态变量 hashSet 信息。

[arthas@19856]$ ognl ‘@com.Arthas@hashSet’
@HashSet[
@String[count1],
@String[count2],
@String[count29],
@String[count28],
@String[count0],
@String[count27],
@String[count5],
@String[count26],
@String[count6],
@String[count25],
@String[count3],
@String[count24],
ognl 可以做很多事情 看集合大小,动态添加值,可以参考 ognl 表达式特殊用法( https://github.com/alibaba/arthas/issues/71 )。

3.2.9 trace 命令可以跟踪统计方法耗耗时
访问接口 /getUser ,可以看到耗时信息,看到 com.UserServiceImpl:get()方法耗时较高。

3.2.10 统计方法耗时
使用 monitor 命令监控统计方法的执行情况。
image.png
每5秒统计一次 com.UserServiceImpl 类的 get 方法执行情况。monitor -c 5 com.UserServiceImpl get

3.2.11 想观察方法信息
使用 watch 命令轻松查看输入输出参数以及异常等信息

USAGE:
watch [-b] [-e] [-x ] [-f] [-h] [-n ] [-E] [-M ] [-s] class-pattern method-pattern express [condition-express]

SUMMARY:
Display the input/output parameter, return object, and thrown exception of specified method invocation
The express may be one of the following expression (evaluated dynamically):
target : the object
clazz : the object’s class
method : the constructor or method
params : the parameters array of method
params[0..n] : the element of parameters array
returnObj : the returned object of method
throwExp : the throw exception of method
isReturn : the method ended by return
isThrow : the method ended by throwing exception
#cost : the execution time in ms of method invocation
Examples:
watch -b org.apache.commons.lang.StringUtils isBlank params
watch -f org.apache.commons.lang.StringUtils isBlank returnObj
watch org.apache.commons.lang.StringUtils isBlank ‘{params, target, returnObj}’ -x 2
watch -bf StringUtils isBlank params
watch
StringUtils isBlank params[0]
watch StringUtils isBlank params[0] params[0].length==1
watch
StringUtils isBlank params ‘#cost>100’
watch -E -b org.apache.commons.lang.StringUtils isBlank params[0]

WIKI:
https://alibaba.github.io/arthas/watch

常用操作:

3.2.12 观察方法的调用路径
使用 stack命令查看方法的调用信息。
stack com.UserServiceImpl mysql
image.png

3.2.13 方法调用时空隧道
使用 tt 命令记录方法执行的详细情况。
tt 命令方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测 。
image.png
常用操作:
开始记录方法调用信息:tt -t com.UserServiceImpl check

可以看到记录中 INDEX=1001 的记录的 IS-EXP = true ,说明这次调用出现异常。

查看记录的方法调用信息: tt -l
image.png
查看调用记录的详细信息(-i 指定 INDEX): tt -i 1001
image.png
可以看到 INDEX=1001 的记录的异常信息。

重新发起调用,使用指定记录,使用 -p 重新调用。
image.png