-
概述
Arthas是一个开源的线上诊断工具,可以实时查看线上代码运行情况,详情参考Arthas -
安装
1.下载jar包即可 https://alibaba.github.io/arthas/arthas-boot.jar
2.以jar的允许方式就可以了java -jar arthas-boot.jar 进程id(可使用jps列出所有jvm进程)
-
命令列表
-
jad命令(获取已加载类的源码)
//主要用来看已经加载了类的源码,一般用于动态加载的class的源码比较方便 [arthas@773]$ jad com/example/jvm/Hello ClassLoader: +-sun.misc.Launcher$AppClassLoader@18b4aac2 +-sun.misc.Launcher$ExtClassLoader@362d9542 Location: /Users/wuxinxin/IdeaProjects/javaseTest/target/classes/ /* * Decompiled with CFR. */ package com.example.jvm; import java.io.IOException; public class Hello { public static void main(String[] args) throws IOException { System.out.println("Hello, World"); System.in.read(); } } Affect(row-cnt:1) cost in 354 ms.
-
ognl(查看静态变量值)
[arthas@909]$ ognl @com.example.jvm.Hello@list.size() @Integer[2] [arthas@909]$ [arthas@909]$ ognl @com.example.jvm.Hello@list @ArrayList[ @String[aa], @String[cc], ]
-
trace(跟踪指定方法的执行耗时情况)
说明:可以很好的跟踪线上运行耗时情况,打印线上实时的执行耗时情况 -
watch(查看某方法的参数列表和结果)
语法:watch 类全路径名 方法名称 ‘{入参对象(Object数组params)和Object结果对象returnObj}’[arthas@1359]$ watch com.example.jvm.arthas.UserService delUser '{params,returnObj.toString()}' Press Q or Ctrl+C to abort. Affect(class-cnt:1 , method-cnt:1) cost in 43 ms. ts=2020-05-24 16:29:53; [cost=1.942564ms] result=@ArrayList[ @Object[][isEmpty=false;size=1], @String[[liujing, wxx2222, wxx3333]], ] [arthas@1359]$ watch com.example.jvm.arthas.UserService checkUser '{params,returnObj.toString()}' Press Q or Ctrl+C to abort. Affect(class-cnt:1 , method-cnt:1) cost in 12 ms. ts=2020-05-24 16:30:53; [cost=0.151088ms] result=@ArrayList[ @Object[][isEmpty=false;size=1], @String[0], ] [arthas@1359]$ watch com.example.jvm.arthas.UserService checkUser '{params[0],returnObj.toString()}' Press Q or Ctrl+C to abort. Affect(class-cnt:1 , method-cnt:1) cost in 9 ms. ts=2020-05-24 16:31:53; [cost=0.125463ms] result=@ArrayList[ @Integer[0], @String[0], ]
-
stack(查看运行时某方法的调用栈)
[arthas@1415]$ stack com.example.jvm.arthas.UserService checkUser Press Q or Ctrl+C to abort. Affect(class-cnt:1 , method-cnt:1) cost in 43 ms. ts=2020-05-24 16:58:49;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@18b4aac2 @com.example.jvm.arthas.UserService.checkUser() at com.example.jvm.arthas.UserService.delUser(UserService.java:58) at com.example.jvm.arthas.ArthasTest.main(ArthasTest.java:39)
-
tt命令(又称为时空隧道,就是可以记录当时调用情况,并且可以重复执行)
//tt -t 类路径名称 方法名称(命令执行那一刻,会记录这个方法的所有执行记录) [arthas@1642]$ tt -t com.example.jvm.arthas.UserService delUser Press Q or Ctrl+C to abort. Affect(class-cnt:1 , method-cnt:1) cost in 42 ms. INDEX TIMESTAMP COST(ms) IS-RE IS-EXP OBJECT CLASS METHOD T ---------------------------------------------------------------------------------------------------------------------------- 1000 2020-05-24 17:35: 2.019116 true false 0x5fd0d5ae UserService delUser 05 //tt -i index 可以查看某个记录详情,甚至可以看到入参和返回值 [arthas@1642]$ tt -i 1000 INDEX 1000 GMT-CREATE 2020-05-24 17:35:05 COST(ms) 2.019116 OBJECT 0x5fd0d5ae CLASS com.example.jvm.arthas.UserService METHOD delUser IS-RETURN true IS-EXCEPTION false PARAMETERS[0] @Integer[0] RETURN-OBJ @ArrayList[ @String[liujing], @String[wxx2222], @String[wxx3333], ] Affect(row-cnt:1) cost in 6 ms. //tt -i index -p可以在当时条件下,再重复调用(慎用,发生真实调用) [arthas@1642]$ tt -i 1000 -p RE-INDEX 1000 GMT-REPLAY 2020-05-24 17:40:35 OBJECT 0x5fd0d5ae CLASS com.example.jvm.arthas.UserService METHOD delUser PARAMETERS[0] @Integer[0] IS-RETURN true IS-EXCEPTION false COST(ms) 0.674845 RETURN-OBJ @ArrayList[ @String[wxx2222], @String[wxx3333], ] Time fragment[1000] successfully replayed 1 times.
-
thread命令(查看线程状态)
[arthas@1642]$ thread //这里展示当前jvm进程的所有线程情况,有几个比较重要的字段需要关注 //1.name 是线程的名称 //2.state表示线程状态 a.BLOCKED 一般使用了 synchronized的锁等待 b.WAITING 一般是无限等待,需要唤醒 park(reentrantLock.lock()内部是park方式实现,这种锁等待也是这种状态) c.TIMED_WAITI 一般是指有时间的等待,自动唤醒(sleep,LockSupport.parkNanos) //3.cpu ,如果有cpu飙高情况,可以看看哪个线程导致 //4.thread id 可以看具体线程情况,比如WAITING是在哪里等待,都能看到
syn关键字方式加锁状态详情//BLOCKED状态测试,没抢到锁的是BLOCKED,抢到锁的但是sleep为TIMED_WAI public static void main(String[] args) throws Exception { ArthasTest arthasTest = new ArthasTest(); //测试锁的情况 for(int i=0;i<10;i++){ Thread thread = new Thread(new Runnable() { @Override public void run() { arthasTest.lock1(); } }); thread.setName("wxx"+i+"线程"); thread.start(); } System.in.read(); } public synchronized void lock1(){ try { Thread.sleep(60000); } catch (InterruptedException e) { e.printStackTrace(); } }
lock方式加锁状态public static void main(String[] args) throws Exception { ArthasTest arthasTest = new ArthasTest(); ReentrantLock reentrantLock=new ReentrantLock(); for(int i=0;i<10;i++){ Thread thread = new Thread(new Runnable() { @Override public void run() { arthasTest.lock1(reentrantLock); } }); thread.setName("wxx"+i+"线程"); thread.start(); } System.in.read(); } public void lock1(ReentrantLock reentrantLock){ reentrantLock.lock(); try { Thread.sleep(60000); } catch (InterruptedException e) { e.printStackTrace(); } reentrantLock.unlock(); }
-
总结
1.可以查看线上实时情况,比如cpu飙高,哪个线程,哪行代码
2.校验允许结果和预期结果,查看stack, 入参和结果
3.运行时动态加载编译的class,可以直接查看源码
4.接口执行很慢,可以实时查看接口调用栈的耗时详情
转载:https://blog.csdn.net/weixin_38312719/article/details/106313175
查看评论