arthas简单使用
有時(shí)候在生產(chǎn)或者測(cè)試環(huán)境有些方法執(zhí)行比較耗時(shí),一種簡(jiǎn)單粗暴的方法是在可能的地點(diǎn)打日志進(jìn)行監(jiān)視,另一種就是借助于插件進(jìn)行檢測(cè)。最近也是有機(jī)會(huì)了解并實(shí)際運(yùn)用了arthas這個(gè)插件,還是挺方便的。而且也可以用于查看JVM信息、線程信息以及系統(tǒng)屬性等信息。
arthas(中文阿爾薩斯):https://arthas.aliyun.com/zh-cn/
下載:
curl -O https://arthas.aliyun.com/arthas-boot.jar
0.本地準(zhǔn)備一個(gè)java進(jìn)程
package arthas;
public class ArthasTest {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
String test = System.getProperty("test");
while (true) {
String test2 = System.getProperty("test");
if (test2 != null && !test2.equals(test)) {
System.out.println(test2);
test = test2;
}
}
}
}
啟動(dòng)該主類
1.啟動(dòng)arthas
C:UsersqlqDesktopplaintools>java -jar arthas-boot.jar [INFO] arthas-boot version: 3.4.5 [INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER. * [1]: 20384 org.jetbrains.idea.maven.server.RemoteMavenServer36 [2]: 1556 [3]: 28868 arthas.ArthasTest [4]: 16780 org.jetbrains.jps.cmdline.Launcher [5]: 7676 org.jetbrains.jps.cmdline.Launcher 3 [INFO] local lastest version: 3.4.5, remote lastest version: 3.4.6, try to download from remote. [INFO] Start download arthas from remote server: https://arthas.aliyun.com/download/3.4.6?mirror=aliyun [INFO] File size: 11.99 MB, downloaded size: 813.01 KB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 1.58 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 2.36 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 3.14 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 3.93 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 4.71 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 5.49 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 6.28 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 7.06 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 7.33 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 8.81 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 9.59 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 10.37 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 11.56 MB, downloading ... [INFO] Download arthas success. [INFO] arthas home: C:Usersjxrt.arthaslib3.4.6arthas [INFO] Try to attach process 28868 [INFO] Found java home from System Env JAVA_HOME: E:javaJAVA8 [INFO] Attach process 28868 success. [INFO] arthas-client connect 127.0.0.1 3658 ,---. ,------. ,--------.,--. ,--. ,---. ,---. / O | .--. ''--. .--'| '--' | / O ' .-' | .-. || '--'.' | | | .--. || .-. |`. `-. | | | || | | | | | | || | | |.-' | `--' `--'`--' '--' `--' `--' `--'`--' `--'`-----' wiki https://arthas.aliyun.com/doc tutorials https://arthas.aliyun.com/doc/arthas-tutorials.html version 3.4.6 pid 28868 time 2021-01-12 20:54:40 [arthas@28868]$
arthas 會(huì)自動(dòng)檢測(cè)進(jìn)程ID,需要自己選擇一個(gè)PID然后進(jìn)入,上面我輸入3
2.基本命令
1.dashboard 當(dāng)前系統(tǒng)的實(shí)時(shí)數(shù)據(jù)面板:包括線程、JVM、操作系統(tǒng)屬性等
[arthas@28868]$ dashboard ID NAME GROUP PRIORITY STATE %CPU DELTA_TIME TIME INTERRUPTED DAEMON 1 main main 5 RUNNABLE 0.0 0.000 6:9.250 false false -1 C1 CompilerThread3 - -1 - 0.0 0.000 0:0.546 false true -1 C2 CompilerThread2 - -1 - 0.0 0.000 0:0.296 false true -1 C2 CompilerThread0 - -1 - 0.0 0.000 0:0.281 false true -1 C2 CompilerThread1 - -1 - 0.0 0.000 0:0.203 false true 25 arthas-NettyHttpTelnetBootstrap-3-2 system 5 RUNNABLE 0.0 0.000 0:0.078 false true 5 Attach Listener system 5 RUNNABLE 0.0 0.000 0:0.046 false true -1 VM Thread - -1 - 0.0 0.000 0:0.031 false true 2 Reference Handler system 10 WAITING 0.0 0.000 0:0.015 false true 3 Finalizer system 8 WAITING 0.0 0.000 0:0.015 false true 18 arthas-NettyHttpTelnetBootstrap-3-1 system 5 RUNNABLE 0.0 0.000 0:0.015 false true 26 arthas-command-execute system 5 TIMED_WAITING 0.0 0.000 0:0.015 false true 4 Signal Dispatcher system 9 RUNNABLE 0.0 0.000 0:0.000 false true 15 arthas-timer system 5 WAITING 0.0 0.000 0:0.000 false true 19 arthas-NettyWebsocketTtyBootstrap-4-1 system 5 RUNNABLE 0.0 0.000 0:0.000 false true 20 arthas-NettyWebsocketTtyBootstrap-4-2 system 5 RUNNABLE 0.0 0.000 0:0.000 false true 21 arthas-shell-server system 5 TIMED_WAITING 0.0 0.000 0:0.000 false true 22 arthas-session-manager system 5 TIMED_WAITING 0.0 0.000 0:0.000 false true 23 arthas-UserStat system 5 WAITING 0.0 0.000 0:0.000 false true 27 Timer-for-arthas-dashboard-2d53a13f-e23f-4 system 5 RUNNABLE 0.0 0.000 0:0.000 false true -1 GC task thread#7 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#6 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 VM Periodic Task Thread - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#0 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 Service Thread - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#1 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#2 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true Memory used total max usage GC heap 58M 241M 3582M 1.64% gc.ps_scavenge.count 1 ps_eden_space 50M 63M 1322M 3.80% gc.ps_scavenge.time(ms) 7 ps_survivor_space 8M 10M 10M 79.64% gc.ps_marksweep.count 0 ps_old_gen 88K 172032K 2751488K 0.00% gc.ps_marksweep.time(ms) 0 nonheap 27M 28M -1 96.88% code_cache 5M 5M 240M 2.21% metaspace 19M 20M -1 96.71% compressed_class_space 2M 2M 1024M 0.23% direct 0K 0K - 105.88% mapped 0K 0K - 0.00% Runtime os.name Windows 10 os.version 10.0 java.version 1.8.0_171 java.home E:javaJAVA8_171jre systemload.average -1.00 processors 8 timestamp/uptime Tue Jan 12 20:56:26 CST 2021/370s
上面信息可以看到JVM的內(nèi)存信息,也可以查看到每個(gè)區(qū)域的GC信息。同時(shí)也可以看到使用的垃圾收集器是JDK8默認(rèn)的-XX:+UseParallelGC 使用ParallelScavenge + Serial Old(PS MarkSweep)收集器組合
2.thread 查看線程信息
[arthas@28868]$ thread Threads Total: 29, NEW: 0, RUNNABLE: 8, BLOCKED: 0, WAITING: 4, TIMED_WAITING: 2, TERMINATED: 0, Internal threads: 15 ID NAME GROUP PRIORITY STATE %CPU DELTA_TIME TIME INTERRUPTED DAEMON 1 main main 5 RUNNABLE 101.42 0.203 8:3.609 false false 2 Reference Handler system 10 WAITING 0.0 0.000 0:0.015 false true 3 Finalizer system 8 WAITING 0.0 0.000 0:0.015 false true 4 Signal Dispatcher system 9 RUNNABLE 0.0 0.000 0:0.000 false true 5 Attach Listener system 5 RUNNABLE 0.0 0.000 0:0.046 false true 15 arthas-timer system 5 WAITING 0.0 0.000 0:0.000 false true 18 arthas-NettyHttpTelnetBootstrap-3-1 system 5 RUNNABLE 0.0 0.000 0:0.015 false true 19 arthas-NettyWebsocketTtyBootstrap-4-1 system 5 RUNNABLE 0.0 0.000 0:0.000 false true 20 arthas-NettyWebsocketTtyBootstrap-4-2 system 5 RUNNABLE 0.0 0.000 0:0.000 false true 21 arthas-shell-server system 5 TIMED_WAITING 0.0 0.000 0:0.000 false true 22 arthas-session-manager system 5 TIMED_WAITING 0.0 0.000 0:0.000 false true 23 arthas-UserStat system 5 WAITING 0.0 0.000 0:0.000 false true 25 arthas-NettyHttpTelnetBootstrap-3-2 system 5 RUNNABLE 0.0 0.000 0:0.125 false true 26 arthas-command-execute system 5 RUNNABLE 0.0 0.000 0:0.015 false true -1 C2 CompilerThread2 - -1 - 0.0 0.000 0:0.328 false true -1 GC task thread#7 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#6 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 VM Periodic Task Thread - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#0 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 C2 CompilerThread0 - -1 - 0.0 0.000 0:0.296 false true -1 Service Thread - -1 - 0.0 0.000 0:0.000 false true -1 C2 CompilerThread1 - -1 - 0.0 0.000 0:0.218 false true -1 GC task thread#1 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 C1 CompilerThread3 - -1 - 0.0 0.000 0:0.609 false true -1 VM Thread - -1 - 0.0 0.000 0:0.031 false true -1 GC task thread#2 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#3 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#5 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#4 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true
例如:thread 1會(huì)打印線程ID 1的棧,通常是main函數(shù)的線程。
[arthas@28868]$ thread 1 | grep 'main('
at arthas.ArthasTest.main(ArthasTest.java:15)
補(bǔ)充:也可以查看線程的阻塞情況,只支持找出synchronized關(guān)鍵字阻塞住的線程, 如果是java.util.concurrent.Lock, 目前還不支持。
如下一段程序:
package arthas;
public class ArthasTest {
public static void main(String[] args) {
MyTask myTask = new MyTask();
for (int i = 0; i < 2; i++) {
new Thread(myTask).start();
}
}
}
class MyTask implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "開(kāi)始執(zhí)行");
synchronized (this) {
System.out.println(Thread.currentThread().getName() + " 占用鎖");
try {
Thread.sleep(1 * 30 * 60 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
結(jié)果:
Thread-0開(kāi)始執(zhí)行
Thread-0 占用鎖
Thread-1開(kāi)始執(zhí)行
可以用jstack查看,也可以用arthas:如下
[arthas@22336]$ thread -b
"Thread-0" Id=14 TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at arthas.MyTask.run(ArthasTest.java:21)
- locked arthas.MyTask@7253ba6b <---- but blocks 1 other threads!
at java.lang.Thread.run(Thread.java:748)
[arthas@22336]$ thread
Threads Total: 31, NEW: 0, RUNNABLE: 8, BLOCKED: 1, WAITING: 4, TIMED_WAITING: 3, TERMINATED: 0, Internal threads: 15
ID NAME GROUP PRIORITY STATE %CPU DELTA_TIME TIME INTERRUPTED DAEMON
2 Reference Handler system 10 WAITING 0.0 0.000 0:0.000 false true
3 Finalizer system 8 WAITING 0.0 0.000 0:0.000 false true
4 Signal Dispatcher system 9 RUNNABLE 0.0 0.000 0:0.000 false true
5 Attach Listener system 5 RUNNABLE 0.0 0.000 0:0.031 false true
18 arthas-timer system 5 WAITING 0.0 0.000 0:0.000 false true
21 arthas-NettyHttpTelnetBootstrap-3-1 system 5 RUNNABLE 0.0 0.000 0:0.031 false true
22 arthas-NettyWebsocketTtyBootstrap-4-1 system 5 RUNNABLE 0.0 0.000 0:0.000 false true
23 arthas-NettyWebsocketTtyBootstrap-4-2 system 5 RUNNABLE 0.0 0.000 0:0.000 false true
24 arthas-shell-server system 5 TIMED_WAITING 0.0 0.000 0:0.000 false true
25 arthas-session-manager system 5 TIMED_WAITING 0.0 0.000 0:0.000 false true
26 arthas-UserStat system 5 WAITING 0.0 0.000 0:0.000 false true
28 arthas-NettyHttpTelnetBootstrap-3-2 system 5 RUNNABLE 0.0 0.000 0:0.093 false true
29 arthas-command-execute system 5 RUNNABLE 0.0 0.000 0:0.015 false true
14 Thread-0 main 5 TIMED_WAITING 0.0 0.000 0:0.000 false false
15 Thread-1 main 5 BLOCKED 0.0 0.000 0:0.000 false false
16 DestroyJavaVM main 5 RUNNABLE 0.0 0.000 0:0.343 false false
-1 C2 CompilerThread2 - -1 - 0.0 0.000 0:0.218 false true
-1 GC task thread#7 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true
-1 GC task thread#6 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true
-1 VM Periodic Task Thread - -1 - 0.0 0.000 0:0.000 false true
-1 GC task thread#0 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true
-1 C2 CompilerThread0 - -1 - 0.0 0.000 0:0.203 false true
-1 Service Thread - -1 - 0.0 0.000 0:0.000 false true
-1 C2 CompilerThread1 - -1 - 0.0 0.000 0:0.218 false true
-1 GC task thread#1 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true
-1 C1 CompilerThread3 - -1 - 0.0 0.000 0:0.640 false true
-1 VM Thread - -1 - 0.0 0.000 0:0.015 false true
-1 GC task thread#2 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true
-1 GC task thread#3 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true
-1 GC task thread#5 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true
-1 GC task thread#4 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true
[arthas@22336]$ thread 15
"Thread-1" Id=15 BLOCKED on arthas.MyTask@7253ba6b owned by "Thread-0" Id=14
at arthas.MyTask.run(ArthasTest.java:19)
- blocked on arthas.MyTask@7253ba6b
at java.lang.Thread.run(Thread.java:748)
thread -b找出當(dāng)前阻塞其他線程的線程。 可以看到 Thread-0 阻塞了其他一個(gè)線程
Thread 查看線程狀態(tài)可以看到ID為15的Thread-1處于阻塞狀態(tài)。
Thread 15 查看具體的信息,可以看到當(dāng)前阻塞的資源被哪個(gè)線程占有等情況。
3. jad 反編譯類信息
[arthas@28868]$ jad arthas.ArthasTest
ClassLoader:
+-sun.misc.Launcher$AppClassLoader@18b4aac2
+-sun.misc.Launcher$ExtClassLoader@3af87f7
Location:
/E:/xiangmu/MvnPro/target/classes/
/*
* Decompiled with CFR.
*/
package arthas;
public class ArthasTest {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
String test = System.getProperty("test");
while (true) {
String test2;
if ((test2 = System.getProperty("test")) == null || test2.equals(test)) {
continue;
}
System.out.println(test2);
test = test2;
}
}
}
4.開(kāi)啟保存日志
options 查看配置,相當(dāng)于查看arthas內(nèi)置的全局配置屬性
options save-result true 開(kāi)啟保存日志。會(huì)保存到{user}/logsarthas-cache/result.log 中
5.退出
如果只是退出當(dāng)前的連接,可以用quit或者exit命令。Attach到目標(biāo)進(jìn)程上的arthas還會(huì)繼續(xù)運(yùn)行,端口會(huì)保持開(kāi)放,下次連接時(shí)可以直接連接上。
如果想完全退出arthas,可以執(zhí)行stop命令。
3. 實(shí)操
1. 修改以及查看JVM的環(huán)境變量和JVM的系統(tǒng)屬性
sysenv 查看JVM的環(huán)境變量
sysprop 查看JVM的所有的系統(tǒng)屬性
sysprop java.version 查看單個(gè)系統(tǒng)的屬性
sysprop user.country US 修改user.country 屬性的值為US
比如上面修改test 屬性為 testValue,修改之后會(huì)被程序System.getProperty(key) 獲取到
[arthas@28868]$ sysprop test testValue Successfully changed the system property. KEY VALUE ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- test testValue [arthas@28868]$ sysprop test KEY VALUE ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- test testValue
我們到IDEA查看main線程打出的信息:testValue
2. 監(jiān)視方法的執(zhí)行時(shí)長(zhǎng)以及方法的返回值
比如如下簡(jiǎn)單的Controller和Service:
controller:
package com.xm.ggn.controller;
import com.xm.ggn.service.common.MessageService2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@Value("${test:defaultValue}")
private String test;
@RequestMapping("test")
public String test() {
return test;
}
@Autowired
private MessageService2 messageService;
@RequestMapping("tx1")
public void tx1() {
messageService.tx1();
}
@RequestMapping("tx2")
public void tx2() {
messageService.tx2();
}
@RequestMapping("tx4")
public void tx4() {
messageService.tx4();
}
}
service:
package com.xm.ggn.service.common;
public interface MessageService2 {
void tx1();
void tx2();
void tx3();
void tx4();
}
serviceimpl:
package com.xm.ggn.service.common.impl;
import com.xm.ggn.bean.common.Message;
import com.xm.ggn.mapper.common.MessageMapper;
import com.xm.ggn.service.common.MessageService2;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
@Service
//@Transactional
public class MessageService2Impl implements MessageService2 {
@Autowired
private MessageMapper messageMapper;
@Override
@Transactional
public void tx1() {
// 調(diào)用tx3方法會(huì)回滾,因?yàn)檫@里有事務(wù)直接,會(huì)走代理,且tx3方法會(huì)加入本事務(wù)
tx3();
}
@Override
public void tx2() {
try {
Thread.sleep(1 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 調(diào)用tx3方法不會(huì)回滾,因?yàn)檫@里沒(méi)有事務(wù)。即使tx3有事務(wù)也不會(huì)走代理,因?yàn)橥ㄟ^(guò)內(nèi)部方法調(diào)用不會(huì)走代理。解決辦法查看tx4 方法
tx3();
}
@Override
@Transactional
public void tx3() {
Message message = new Message();
message.setTitle("tx3");
messageMapper.insert(message);
int i = 1 / 0;
}
// 這樣進(jìn)行方法內(nèi)部調(diào)用AOP會(huì)生效,主啟動(dòng)類加@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true) 注解
@Override
public void tx4() {
MessageService2 messageService = (MessageService2) AopContext.currentProxy();
// 這樣調(diào)用tx3會(huì)進(jìn)行回滾,走的是代理類的方法
messageService.tx3();
}
}
啟動(dòng)應(yīng)用后啟動(dòng)arthas并且監(jiān)視對(duì)應(yīng)進(jìn)程
1. 搜索類以及反編譯查看AOP增強(qiáng)的類
1. 搜索:模糊搜索
[arthas@13232]$ sc *.MessageService2 com.xm.ggn.service.common.MessageService2 com.xm.ggn.service.common.impl.MessageService2Impl com.xm.ggn.service.common.impl.MessageService2Impl$$EnhancerBySpringCGLIB$$7fa3a2fc Affect(row-cnt:3) cost in 56 ms.
如果查看加載的所有類,可以用:
sc *
2. 反編譯查看AOP增強(qiáng)的類
[arthas@13232]$ jad com.xm.ggn.service.common.impl.MessageService2Impl$$EnhancerBySpringCGLIB$$7fa3a2fc
ClassLoader:
+-sun.misc.Launcher$AppClassLoader@18b4aac2
+-sun.misc.Launcher$ExtClassLoader@3c22fc4c
Location:
/E:/xiangmu/bs-media/media-server/target/classes/
/*
* Decompiled with CFR.
*
* Could not load the following classes:
* com.xm.ggn.service.common.impl.MessageService2Impl
*/
package com.xm.ggn.service.common.impl;
import com.xm.ggn.service.common.impl.MessageService2Impl;
import java.lang.reflect.Method;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.SpringProxy;
import org.springframework.aop.TargetClassAware;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Dispatcher;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.NoOp;
public class MessageService2Impl$$EnhancerBySpringCGLIB$$7fa3a2fc
extends MessageService2Impl
implements SpringProxy,
Advised,
Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
...
}
2. 檢測(cè)方法的執(zhí)行時(shí)長(zhǎng): trace
比如檢測(cè):com.xm.ggn.controller.TestController 類的所有方法,如下:
[arthas@13232]$ trace com.xm.ggn.controller.TestController *
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 5) cost in 93 ms, listenerId: 1
`---ts=2021-01-12 21:15:57;thread_name=http-nio-8088-exec-1;id=108;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@3ee39a1c
`---[45.0785ms] com.xm.ggn.controller.TestController:tx4() [throws Exception]
+---[44.0299ms] com.xm.ggn.service.common.MessageService2:tx4() #40 [throws Exception]
`---throw:java.lang.ArithmeticException #39 [/ by zero]
trace還有好幾個(gè)參數(shù)可以過(guò)濾以及支持檢測(cè)多個(gè)類的多個(gè)方法以及根據(jù)時(shí)長(zhǎng)過(guò)濾等
補(bǔ)充:用trace命令檢測(cè)多個(gè)類的多個(gè)方法,形成調(diào)用鏈檢測(cè)
比如如下
(1) Service1
package com.xm.ggn.test.arthas;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
/**
* @author: 喬利強(qiáng)
* @date: 2021/2/7 14:37
* @description:
*/
@Service
@Slf4j
public class ArthasTestService {
@Autowired
private ArthasTestService2 arthasTestService2;
public void method1() {
log.debug("method1");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ignore) {
}
this.method2();
this.method3();
}
public void method2() {
log.debug("method2");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException ignore) {
}
arthasTestService2.method1();
arthasTestService2.method2();
}
public void method3() {
log.debug("method3");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException ignore) {
}
}
}
(2)Service2
package com.xm.ggn.test.arthas;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
/**
* @author: 喬利強(qiáng)
* @date: 2021/2/7 14:37
* @description:
*/
@Service
@Slf4j
public class ArthasTestService2 {
public void method1() {
log.debug("method1");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException ignore) {
}
}
public void method2() {
log.debug("method2");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException ignore) {
}
}
}
(3)Controller
package com.xm.ggn.test.arthas;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author: 喬利強(qiáng)
* @date: 2021/2/7 14:34
* @description:
*/
@RestController
@RequestMapping("/arthas")
public class ArthasTestCcontroller {
@Autowired
private ArthasTestService arthasTestService;
@GetMapping("testTrace")
public void testTrace() {
arthasTestService.method1();
}
}
(4)測(cè)試:
1》trace檢測(cè)單個(gè)類,結(jié)果如下: 可以看到?jīng)]監(jiān)測(cè)ArthasTestService2 內(nèi)部調(diào)用時(shí)長(zhǎng)
[arthas@28892]$ sc *.ArthasTestService*
com.xm.ggn.test.arthas.ArthasTestService
com.xm.ggn.test.arthas.ArthasTestService2
Affect(row-cnt:2) cost in 50 ms.
[arthas@28892]$ trace com.xm.ggn.test.arthas.ArthasTestService *
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 4) cost in 83 ms, listenerId: 1
`---ts=2021-02-07 19:32:08;thread_name=http-nio-8088-exec-1;id=12e;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@87060c0
`---[9003.109599ms] com.xm.ggn.test.arthas.ArthasTestService:method1()
+---[0.035ms] org.slf4j.Logger:debug() #22
+---[5002.6882ms] com.xm.ggn.test.arthas.ArthasTestService:method2() #28
| `---[5002.1293ms] com.xm.ggn.test.arthas.ArthasTestService:method2()
| +---[0.008ms] org.slf4j.Logger:debug() #34
| +---[1000.8634ms] com.xm.ggn.test.arthas.ArthasTestService2:method1() #40
| `---[2000.6096ms] com.xm.ggn.test.arthas.ArthasTestService2:method2() #41
`---[3000.115601ms] com.xm.ggn.test.arthas.ArthasTestService:method3() #29
`---[3000.07ms] com.xm.ggn.test.arthas.ArthasTestService:method3()
`---[0.007ms] org.slf4j.Logger:debug() #45
2》 監(jiān)測(cè)兩個(gè)類的多個(gè)方法: 可以看到也監(jiān)測(cè)了ArthasTestService2的相關(guān)方法
[arthas@28892]$ trace -E com.xm.ggn.test.arthas.ArthasTestService|com.xm.ggn.test.arthas.ArthasTestService2 method1|method2|method3
Press Q or Ctrl+C to abort.
Affect(class count: 2 , method count: 5) cost in 122 ms, listenerId: 3
`---ts=2021-02-07 19:34:51;thread_name=http-nio-8088-exec-4;id=131;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@87060c0
`---[9002.5463ms] com.xm.ggn.test.arthas.ArthasTestService:method1()
+---[0.0627ms] org.slf4j.Logger:debug() #22
+---[5001.5262ms] com.xm.ggn.test.arthas.ArthasTestService:method2() #28
| `---[5001.484ms] com.xm.ggn.test.arthas.ArthasTestService:method2()
| +---[0.008101ms] org.slf4j.Logger:debug() #34
| +---[1000.377399ms] com.xm.ggn.test.arthas.ArthasTestService2:method1() #40
| | `---[1000.288999ms] com.xm.ggn.test.arthas.ArthasTestService2:method1()
| | `---[0.0178ms] org.slf4j.Logger:debug() #18
| `---[2000.178ms] com.xm.ggn.test.arthas.ArthasTestService2:method2() #41
| `---[2000.134ms] com.xm.ggn.test.arthas.ArthasTestService2:method2()
| `---[0.0112ms] org.slf4j.Logger:debug() #26
`---[3000.27ms] com.xm.ggn.test.arthas.ArthasTestService:method3() #29
`---[3000.235499ms] com.xm.ggn.test.arthas.ArthasTestService:method3()
`---[0.007101ms] org.slf4j.Logger:debug() #45
這里暫時(shí)沒(méi)找到監(jiān)測(cè)兩個(gè)類或多個(gè)類所有方法的套路~~~
結(jié)果解釋:
(1)[5001.5262ms] com.xm.ggn.test.arthas.ArthasTestService:method2() #28當(dāng)前節(jié)點(diǎn)在當(dāng)前步驟的耗時(shí),單位為毫秒。 #28 表示在源文件的第28行。
(2)還有另一種寫法:[min=0.020435ms,max=0.022325ms,total=0.04276ms,count=2] org.springframework.util.Assert:isTrue() #95表示對(duì)該方法中相同的方法調(diào)用進(jìn)行了合并。比如:
if ("1".equals(a) && "2".equals(b)) {
// doXXX
}
3.查看某個(gè)類調(diào)用過(guò)程中的返回值: 比如觀察方法出參和返回值 watch
[arthas@19792]$ watch com.xm.ggn.controller.TestController * "{params,returnObj}"
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 5) cost in 79 ms, listenerId: 3
method=com.xm.ggn.controller.TestController.test location=AtExit
ts=2021-01-12 21:32:16; [cost=0.0674ms] result=@ArrayList[
@Object[][isEmpty=true;size=0],
@String[defaultValue],
]
調(diào)用一次test 方法之后結(jié)果如上。可以看到參數(shù)為空,返回值是一個(gè)String值為"defaultValue"。
這個(gè)結(jié)果可能不太明顯,增加一個(gè)測(cè)試用例:
(1)Controller增加一個(gè)方法:
@RequestMapping("testMap")
public Map test(String key1, String key2) {
HashMap<String, Object> stringObjectHashMap = new HashMap<>();
stringObjectHashMap.put(key1, key1);
stringObjectHashMap.put(key2, key2);
return stringObjectHashMap;
}
(2)arthas檢測(cè): -x指定輸出結(jié)果的屬性遍歷深度,默認(rèn)為 1
[arthas@27848]$ watch com.xm.ggn.controller.TestController * "{params,returnObj}" -x 3
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 6) cost in 38 ms, listenerId: 5
(3)訪問(wèn):
http://localhost:8088/testMap?key1=111&key2=222
(4)arthas控制臺(tái)輸出
method=com.xm.ggn.controller.TestController.test location=AtExit
ts=2021-01-12 21:40:26; [cost=0.0351ms] result=@ArrayList[
@Object[][
@String[111],
@String[222],
],
@HashMap[
@String[111]:@String[111],
@String[222]:@String[222],
],
]
補(bǔ)充:第一次運(yùn)行jar包選擇進(jìn)程進(jìn)入的時(shí)候會(huì)自動(dòng)從互聯(lián)網(wǎng)下載幾個(gè)依賴包,自動(dòng)放在 ${user}/.arthas/lib。如果是離線環(huán)境可以將lib下面的包傳到離線的服務(wù)器,啟動(dòng)的時(shí)候指定路徑:如下:
java -jar arthas-boot.jar --arthas-home C:UsersqlqDesktopplaintoolsarthaslib3.4.5arthas
--arthas-home 指定依賴包的路徑
補(bǔ)充:Arthas目前支持Web Console,用戶在attach成功之后,可以直接訪問(wèn):http://127.0.0.1:3658/。默認(rèn)情況下,arthas只listen 127.0.0.1,所以如果想從遠(yuǎn)程連接,則可以使用--target-ip參數(shù)指定listen的IP,更多參考-h的幫助說(shuō)明。
補(bǔ)充:logger查看以及修改日志級(jí)別
[arthas@11520]$ logger #查看日志級(jí)別
name ROOT
class ch.qos.logback.classic.Logger
classLoader sun.misc.Launcher$AppClassLoader@18b4aac2
classLoaderHash 18b4aac2
level INFO
effectiveLevel INFO
additivity true
codeSource file:/E:/Maven/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar
appenders name CONSOLE
class ch.qos.logback.core.ConsoleAppender
classLoader sun.misc.Launcher$AppClassLoader@18b4aac2
classLoaderHash 18b4aac2
target System.out
[arthas@11520]$ logger --name ROOT --level debug #修改日志級(jí)別
Update logger level success.
[arthas@11520]$ logger #查看日志級(jí)別
name ROOT
class ch.qos.logback.classic.Logger
classLoader sun.misc.Launcher$AppClassLoader@18b4aac2
classLoaderHash 18b4aac2
level DEBUG
effectiveLevel DEBUG
additivity true
codeSource file:/E:/Maven/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar
appenders name CONSOLE
class ch.qos.logback.core.ConsoleAppender
classLoader sun.misc.Launcher$AppClassLoader@18b4aac2
classLoaderHash 18b4aac2
target System.out
補(bǔ)充:sc 也可以查看類以及靜態(tài)變量的信息,如下:
[arthas@9432]$ sc -d -f com.xm.ggn.test.FieldTest
class-info com.xm.ggn.test.FieldTest
code-source /E:/xiangmu/bs-media/media-server/target/classes/
name com.xm.ggn.test.FieldTest
isInterface false
isAnnotation false
isEnum false
isAnonymousClass false
isArray false
isLocalClass false
isMemberClass false
isPrimitive false
isSynthetic false
simple-name FieldTest
modifier public
annotation
interfaces
super-class +-java.lang.Object
class-loader +-sun.misc.Launcher$AppClassLoader@18b4aac2
+-sun.misc.Launcher$ExtClassLoader@707ed9b0
classLoaderHash 18b4aac2
fields name test
type java.lang.String
modifier final,public,static
value 123
name name
type java.lang.String
modifier private
也可以使用ognl獲取靜態(tài)變量:
[arthas@9432]$ ognl '@com.xm.ggn.test.FieldTest@test' @String[123]
總結(jié)
以上是生活随笔為你收集整理的arthas简单使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 深入解析IE兼容模式
- 下一篇: 郭明錤修正此前预测,苹果将推迟至 202