一、Arthas简介
Arthas是alibaba推出的一款JVM性能诊断调优的工具,也可以称之为是线上监控诊断产品,通过全局的视角可以实时的查看应用load、内存、GC、线程的状态信息,并且还可以在不修改应用代码的前提下,对业务问题进行诊断,包括查看方法调用的出参、入参、异常等,监测方法执行耗时,类加载信息等等,大大提升了线上问题的排查效率。
二、Arthas场景
一般情况下,本地开发环境不能访问生产环境,如果在生产环境中遇到了问题,那么就无法使用IDE远程调试,更加糟糕的是在生产环境中调试是不可接受的,因为它会停止所有线程,导致服务暂停。
开发人员可以尝试在测试环境或者预发环境中复现生产环境中的问题,但是某些问题无法在不同的环境中轻松的复现,甚至在重启后就消失了。
如果考虑在代码中添加一些日志帮助解决问题,就必须经历以下阶段:测试、预发、然后生产,这种方法效率比较低,更糟糕的是,该问题可能无法解决,因为一旦JVM重新启动,可能无法复现。
那么Arthas可以解决这些问题,开发人员可以在线解决生产问题,无需JVM启动,无需代码更改,Arthas作为观察者永远不会暂停正在运行的线程。
三、Arthas解决哪些问题?
- 这个类从哪个jar包加载的,为什么各种报错
- 我改的代码为什么没有执行到?难道是我没有Commit?分支搞错了?
- 遇到问题无法在线上debug,难道只能通过加日志在重新发布吗?
- 线上遇到某个用户的数据处理有问题,但线上同样无法debug,线下无法重现
- 是否有一个全局视角来查看系统的运行状况?
- 有什么办法可以监控到JVM的实时运行状态?
- 怎么快速定位应用的热点,生成火焰图?
- 怎样直接从JVM内查找某个类的实例?
四、Arthas下载
curl -O https://arthas.aliyun.com/arthas-boot.jar
五、Arthas启动
- 启动arthas-boot.jar
java -jar arthas-boot.jar
-
选择监控的应用进程
- 这个时候会列出所有可监控的应用进程,输入对应的编号即可
六、全局监控仪表
-
dashboard
- dashboard命令,可以实时的显示出所有线程的情况、内存的情况、运行环境信息、cpu占用等情况。
-
thread
- thread命令,可以显示出所有线程信息
-
thread id
- thread 线程对应的ID,可以显示线程的具体信息
七、方法级别监控
我们在调优的时候,需要定位到应用的具体方法,所以arthas提供了一套对于方法的监控,但是方法的监控我们需要手动输入很多参数,为了方便,我们就在IDEA中安装arthas idea插件,可以自动生成带参数的命令,只需要复制即可。
1、安装插件
2、watch
watch命令用来查看方法的一些具体信息,比如入参、出参、异常等情况。
-n:执行次数
-x:每次调用监控的层级深度
watch com.cy.example.Demo testHandler '{params,returnObj,throwExp}' -n 5 -x 3
3、trace
trace命令用于查看方法的运行耗时
-n:执行次数
trace com.cy.example.Demo testHandler -n 5 --skipJDKMethod false
3、stack
stack命令用于查看该方法在哪被调用了
-n:执行次数
stack com.cy.example.Demo testHandler -n 5
八、类级别监控
1、sc
sc命令:查看JVM已加载的类信息
# 显示JVM已加载的类信息
sc com.cy.example.Demo
# 打印出类信息
sc -d com.cy.example.Demo
2、sm
sm命令:查看JVM已加载类的方法信息
# 查看加载类的方法信息
sm com.cy.example.Demo
# 查看加载类的方法详细信息
sm -d com.cy.example.Demo
# 查看加载类的指定方法信息
sm com.cy.example.Demo testHandler
# 查看加载类的指定方法的详细信息
sm -d com.cy.example.Demo testHandler
九、线上问题定位
当项目已经上线,出了问题我们需要进行问题定位,可以从以下几点进行查看:
- 代码版本是否引入正确
- CPU占用率过高,哪个程序占用过高
- 死锁的问题
1、反编译
反编译的方式很多,但是大多数都是在开发环境进行反编译,我们需要在线上环境进行反编译,从而能看出我们的代码版本是否引入正确,可能代码版本是1.4,我们引入的是1.3
jad 反编译类名
jad com.cy.example.Demo
2、CPU占用率
# 展示出CPU占用率从高到低指定个数的线程
thread -n 3
3、死锁
可以通过命令直接查看所有的死锁
我这里没有写死锁的代码,因此没有死锁
thread -b
十、线上代码热更新
在不停止线上服务的情况下修改代码
需要注意的是,热更新的字节码文件不能新增属性和方法,并且热更新后原来的类不能恢复
# 通过jad对文件进行反编译,并且输出到其他地方
jad Demo > /usr/NewDemo.java
# 对NewDemo.java进行更改代码
# 使用mc在内存中对NewDemo.java进行编译
mc /usr/NewDemo.java -d /usr
# 热更新
redefine /usr/NewDemo.class