1、下载
wget https://alibaba.github.io/arthas/arthas-boot.jar
启动 java -jar arthas-boot.jar
2、相关命令
1)输入dashboard,仪表盘显示当前进程相关信息
ID 线程ID
NAME 线程名称
GROUP 线程组
说明
ID: Java级别的线程ID,注意这个ID不能跟jstack中的nativeID一一对应
NAME: 线程名
GROUP: 线程组名
PRIORITY: 线程优先级, 1~10之间的数字,越大表示优先级越高
STATE: 线程的状态
CPU%: 线程消耗的cpu占比,采样100ms,将所有线程在这100ms内的cpu使用量求和,再算出每个线程的cpu使用占比。
TIME: 线程运行总时间,数据格式为分:秒
INTERRUPTED: 线程当前的中断位状态
DAEMON: 是否是daemon线程
通过上述信息,可以帮助我们快速定位相关问题线程。
2) 查看具体线程信息 thread 线程id
3) 查看类里某个方法的返回值和入参
测试代码:
public class Demo1 { public static void main(String[] args) { System.out.println("currentThreadName=" + Thread.currentThread().getName()); demo1(); } private static void demo1(){ int i = 0; while (true){ i++; String result = sayHello("nick" + i); try { Thread.sleep(1000); }catch (Exception e){ } } } private static String sayHello(String name){ System.out.println("hello, " + name); return "return:" + name; } }
命令+类完全限定名+监测方法+表达式
watch com.example.Demo1 sayHello "{params,returnObj}"
表达式核心变量列表: loader 本次调用类所在的 ClassLoader clazz 本次调用类的 Class 引用 method 本次调用方法反射引用 target 本次调用类的实例 params 本次调用参数列表,这是一个数组,如果方法是无参方法则为空数组 returnObj 本次调用返回的对象。当且仅当 isReturn==true 成立时候有效,表明方法调用是以正常返回的方式结束。如果当前方法无返回值 void,则值为 null throwExp 本次调用抛出的异常。当且仅当 isThrow==true 成立时有效,表明方法调用是以抛出异常的方式结束。 isBefore 辅助判断标记,当前的通知节点有可能是在方法一开始就通知,此时 isBefore==true 成立,同时 isThrow==false 和 isReturn==false,因为在方法刚开始时,还无法确定方法调用将会如何结束。 isThrow 辅助判断标记,当前的方法调用以抛异常的形式结束。 isReturn 辅助判断标记,当前的方法调用以正常返回的形式结束。
watch 查询异常参数
package com.example.arthasdemo2; @Service @Slf4j public class ArthasTestService { public String say(String name){ if("null".equals(name)){ throw new RuntimeException("name is null string"); } return "hello," + name; } }
Controller层代码
@GetMapping("/say") @ResponseBody public String say(@RequestParam String name){ return arthasTestService.say(name); }
执行如下命令
watch com.example.arthasdemo2.ArthasTestService say "params" -x 2 -e -n 1
然后调用接口
http://localhost:8080/say?name=null
当参数为null时,抛出异常。
4)方法调用路径、耗时解析
方法内部调用路径,并输出方法路径上每个节点上耗时
trace com.example.Demo1 sayHello
5) 时空隧道
方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
tt -t com.example.Demo1 demo1
查看抛出的异常
@Service @Slf4j public class ArthasTestService { public void demo2_2(){ log.info("demo2_2"); throw new RuntimeException("demo2_2 error"); } }
tt -t com.example.arthasdemo2.ArthasTestService demo2_2 -n 1
tt -i 1000
6) 查看JVM已加载的类信息
sc -d com.example.Demo1
-d 输出当前类的详细信息,包括这个类所加载的原始文件来源、类的声明、加载的ClassLoader等详细信息。
如果一个类被多个ClassLoader所加载,则会出现多次
7) 退出arthas
quit 退出当前Arthas客户端,其他Arthas客户端不受影响
shutdown 关闭Arthas服务端,所有Arthas客户端全部退出 & 重置所有增强过的类,就不用单独调用reset
3、arthas还提供了Web Console
java -jar arthas-boot.jar --target-ip 192.168.22.89
访问http://192.168.22.89:8563
本机访问
4、jad/mc/redefine 热更新
jad com.exmaple.XXX
com.exmaple是包名
XXX是java类名
查看反编译的源码
创建类LogUtil
package com.example.arthasdemo2; import lombok.extern.slf4j.Slf4j; @Slf4j public class LogUtil { public static void log(String name){ log.debug("hello," + name); } }
Controller层调用该方法
@GetMapping("/logLevel") @ResponseBody public String logLevel(@RequestParam String name){ LogUtil.log(name); return "ok"; }
调用接口http://localhost:8080/logLevel?name=zhangsan,可以看到没有打印debug日志。
查看反编译的源码 jad com.example.arthasdemo2.LogUtil
jad反编译LogUtil代码,保存到 /tmp/LogUtil.java
jad --source-only com.example.arthasdemo2.LogUtil > /tmp/LogUtil.java
利用sc命令搜索jvm已经加载的LogUtil信息
修改/tmp/LogUtil.java的代码利用mc重新编译成class文件
redefine热更新代码
redefine E:/tmp/com/example/arthasdemo2/LogUtil.class
调用接口http://localhost:8080/logLevel?name=zhangsan,可以发现已经有打印
5、生成hprof文件
heapdump
6、查看线程阻塞问题
Controller层代码
@GetMapping("/synchronizedMethodTest1") @ResponseBody public String synchronizedMethod1(){ arthasTestService.synchronizedMethod(); return "ok1"; } @GetMapping("/synchronizedMethodTest2") @ResponseBody public String synchronizedMethod2(){ arthasTestService.synchronizedMethod(); return "ok2"; }
Service层代码
public synchronized void synchronizedMethod(){ log.info("synchronizedMethod"); try { //休眠5分钟 Thread.sleep(300 * 1000); }catch (Exception e){ e.printStackTrace(); } }
分别调用
http://localhost:8080/synchronizedMethodTest1
http://localhost:8080/synchronizedMethodTest2
然后执行thread -b
可以看出http-nio-8080-exec-2线程阻塞了
- locked com.example.arthasdemo2.ArthasTestService@6845c942 <---- but blocks 1 other threads!
参考: 官网地址 https://arthas.aliyun.com/doc/
作者:Work Hard Work Smart
出处:http://www.cnblogs.com/linlf03/
欢迎任何形式的转载,未经作者同意,请保留此段声明!