- 概述
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.接口执行很慢,可以实时查看接口调用栈的耗时详情