Arthas 是 Alibaba 在 2018 年 9 月开源的 Java 诊断工具。支持 JDK6+, 采用命令行交互模式,可以方便的定位和诊断线上程序运行问题。Arthas 官方文档十分详细,详见:https://alibaba.github.io/arthas
Arthas使用场景
得益于 Arthas 强大且丰富的功能,让 Arthas 能做的事情超乎想象。下面仅仅列举几项常见的使用情况,更多的使用场景可以在熟悉了 Arthas 之后自行探索。 是否有一个全局视角来查看系统的运行状况? 为什么 CPU 又升高了,到底是哪里占用了 CPU ? 运行的多线程有死锁吗?有阻塞吗? 程序运行耗时很长,是哪里耗时比较长呢?如何监测呢? 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception? 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了? 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗? 有什么办法可以监控到 JVM 的实时运行状态?
一、下载arthas-boot.jar
官方提供了两种使用方式 下载arthas-boot.jar 或者直接安装使用 as. sh。 这里说明前一种。我采用下载jar包的方式
curl -O https://alibaba.github.io/arthas/arthas-boot.jar
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 138k 100 138k 0 0 177k 0 --:--:-- --:--:-- --:--:-- 176k
二、运行arthas-boot.jar
整个arthas是java语言开发的,所以可以直接java -jar运行
$ java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.5.3
[INFO] Process 67746 already using port 3658
[INFO] Process 67746 already using port 8563
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 67746 springboot-mybatis-all-1.0.0.jar
[2]: 70997 com.huohuo.service.jvm.DeadLockTest
[3]: 70996 org.jetbrains.jps.cmdline.Launcher
[4]: 70570
[5]: 70798 org.jetbrains.idea.maven.server.RemoteMavenServer36
1
[INFO] arthas home: /Users/huoyajing/.arthas/lib/3.5.5/arthas
[INFO] The target process already listen port 3658, skip attach.
[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.5.5
main_class org.springframework.boot.loader.JarLauncher
pid 67746
time 2022-03-02 15:43:29
[arthas@67746]$
1)选择需要监控的jps进程
也可以直接java -jar arthas-boot.jar pid的方式直接进入主题。
注:[arthas@67746]$表明打开进入了监控客户端,在这里就可以执行相关命令进行查看了。 可以使用quit(退出当前客户端)、stop\shutdown(关闭arthas服务端,并退出所有客户端)。 67746就是PID。
2)可视化界面操作http://127.0.0.1:8563/
除了在命令行查看外,还可以通过浏览器访问http://127.0.0.1:8563/查看。如下图:可以直接操作相关的命令参数
三、常用命令
1)help
[arthas@73120]$ help
NAME DESCRIPTION
help Display Arthas Help
auth Authenticates the current session
keymap Display all the available keymap for the specified connection.
sc Search all the classes loaded by JVM
sm Search the method of classes loaded by JVM
classloader Show classloader info
jad Decompile class
getstatic Show the static field of a class
monitor Monitor method execution statistics, e.g. total/success/failure c
ount, average rt, fail rate, etc.
stack Display the stack trace for the specified class and method
thread Display thread info, thread stack
trace Trace the execution time of specified method invocation.
watch Display the input/output parameter, return object, and thrown exc
eption of specified method invocation
tt Time Tunnel
jvm Display the target JVM information
perfcounter Display the perf counter information.
ognl Execute ognl expression.
mc Memory compiler, compiles java files into bytecode and class file
s in memory.
redefine Redefine classes. @see Instrumentation
ition...)
retransform Retransform classes. @see Instrumentation
s...)
dashboard Overview of target jvm's thread, memory, gc, vm, tomcat info.
dump Dump class byte array from JVM
heapdump Heap dump
options View and change various Arthas options
cls Clear the screen
reset Reset all the enhanced classes
version Display Arthas version
session Display current session information
sysprop Display, and change the system properties.
sysenv Display the system env.
vmoption Display, and update the vm diagnostic options.
logger Print logger info, and update the logger level
history Display command history
cat Concatenate and print files
base64 Encode and decode using Base64 representation
echo write arguments to the standard output
pwd Return working directory name
mbean Display the mbean information
grep grep command for pipes.
tee tee command for pipes.
profiler Async Profiler. https://github.com/jvm-profiling-tools/async-prof
iler
vmtool jvm tool
stop Stop/Shutdown Arthas server and exit the console.
2)dashboard可以查看整个进程的运行情况,线程、内存、GC、运行环境信息
主要展示了三部分内容,线程,jvm,java-env。每过几秒会自动刷新.
3)thread 线程信息
其实就是dashboard获取结果的第一部分
thread -n num 查看前三个线程结果,按照CPU使用情况排序获取
[arthas@16645]$ thread -n 3
"Thread-0" Id=10 cpuUsage=99.16% deltaTime=199ms time=53423ms RUNNABLE
at com.huohuo.service.jvm.ArthasTest.lambda$cpuHigh$1(ArthasTest.java:47)
at com.huohuo.service.jvm.ArthasTest$$Lambda$1/1407343478.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"arthas-command-execute" Id=28 cpuUsage=0.16% deltaTime=0ms time=18ms RUNNABLE
at sun.management.ThreadImpl.dumpThreads0(Native Method)
at sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:448)
at com.taobao.arthas.core.command.monitor200.ThreadCommand.processTopBusyThreads(ThreadCommand.java:206)
at com.taobao.arthas.core.command.monitor200.ThreadCommand.process(ThreadCommand.java:122)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:82)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:18)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:111)
at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:108)
at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:385)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
"C1 CompilerThread2" [Internal] cpuUsage=0.13% deltaTime=0ms time=462ms
4)thread pid 查看某个线程具体结果
5)thread -b 死锁信息,不用pid
[arthas@3987]$ thread -b
"Thread-1" Id=11 BLOCKED on java.lang.Object@57d20628 owned by "Thread-2" Id=12
at com.huohuo.service.jvm.ArthasTest.lambda$deadThread$2(ArthasTest.java:68)
- blocked on java.lang.Object@57d20628
- locked java.lang.Object@7bd50b57 <---- but blocks 1 other threads!
at com.huohuo.service.jvm.ArthasTest$$Lambda$2/2121744517.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
```bash
[arthas@3987]$ thread 10
"Thread-0" Id=10 RUNNABLE
at com.huohuo.service.jvm.ArthasTest.lambda$cpuHigh$1(ArthasTest.java:44)
at com.huohuo.service.jvm.ArthasTest$$Lambda$1/1407343478.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
我们可以很清晰的看到问题所在 ArthasTest.java:44行有问题。
6)jad 类的全路径 反编译
这样可以方便我们查看线上代码是否是正确的版本。
[arthas@3987]$ jad com.huohuo.service.jvm.ArthasTest
//这就是类加载机制AppClassLoader(应用程序类加载器)和ExtClassLoader(扩展类加载器)
ClassLoader:
+-sun.misc.Launcher$AppClassLoader@18b4aac2
+-sun.misc.Launcher$ExtClassLoader@7da3e221
//我的项目所在路径
Location:
/Users/huoyajing/information/spring/springBoot/J2020/springboot-mybatis-all/target/classes/
//如下是类信息,清晰明了,可以很方便查看线上是否是最新代码,太方便了
/*
* Decompiled with CFR.
*/
package com.huohuo.service.jvm;
import java.util.HashSet;
public class ArthasTest {
private static HashSet hashSet = new HashSet();
public static void cpuHigh() {
new Thread(() -> {
while (true) {
// Infinite loop
}
}).start();
}
public static void addHashSetThread() {
new Thread(() -> {
/*29*/ int count = 0;
while (true) {
try {
while (true) {
/*32*/ hashSet.ad
......省略
7)ognl 可以查看/修改系统线上的值
ognl ‘@全路径类目@静态属性名’ 调用静态属性
[arthas@11021]$ ognl @com.huohuo.service.jvm.ArthasTest@hashSet
@HashSet[
@String[count1],
@String[count2],
@String[count0],
@String[count27],
@String[count5],
@String[count26],
@String[count6],
@String[count25],
@String[count3],
@String[count24],
@String[count4],
@String[count23],
@String[count9],
@String[count7],
@String[count8],
@String[count22],
@String[count21],
@String[count20],
@String[count19],
@String[count18],
@String[count17],
@String[count16],
@String[count15],
@String[count14],
@String[count13],
@String[count12],
@String[count11],
@String[count10],
]
[arthas@11021]$ ognl @com.huohuo.service.jvm.ArthasTest@integer
@Integer[2]
ognl ‘@全路径类目@静态方法名(“参数”)’ 调用静态方法
ognl ‘@com.huohuo.service.jvm.ArthasTest@hashSet.add(“huohuo”)’
…
8)sc -d 类全路径 类信息
[arthas@16645]$ sc -d com.huohuo.service.jvm.ArthasTest
class-info com.huohuo.service.jvm.ArthasTest
code-source /Users/huoyajing/information/spring/springBoot/J2020/springbo
ot-mybatis-all/target/classes/
name com.huohuo.service.jvm.ArthasTest
isInterface false
isAnnotation false
isEnum false
isAnonymousClass false
isArray false
isLocalClass false
isMemberClass false
isPrimitive false
isSynthetic false
simple-name ArthasTest
modifier public
annotation
interfaces
super-class +-java.lang.Object
class-loader +-sun.misc.Launcher$AppClassLoader@18b4aac2
+-sun.misc.Launcher$ExtClassLoader@7da3e221
classLoaderHash 18b4aac2
Affect(row-cnt:1) cost in 33 ms.
更多命令请点击
四、 [ERROR] attach fail, targetPid: 77710
java进程是我直接idea,run启动的。
$ java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.5.1
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 70570
[2]: 77709 org.jetbrains.jps.cmdline.Launcher
[3]: 77710 com.huohuo.service.jvm.ArthasTest
3
[INFO] arthas home: /Users/huoyajing/.arthas/lib/3.5.5/arthas
[INFO] Try to attach process 77710
[WARN] Current VM java version: 13 do not match target VM java version: 1.8, attach may fail.
[WARN] Target VM JAVA_HOME is /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre, arthas-boot JAVA_HOME is /Library/Java/JavaVirtualMachines/jdk-13.0.2.jdk/Contents/Home, try to set the same JAVA_HOME.
[ERROR] Start arthas failed, exception stack trace:
com.sun.tools.attach.AgentLoadException: 0
at jdk.attach/sun.tools.attach.HotSpotVirtualMachine.loadAgentLibrary(HotSpotVirtualMachine.java:108)
at jdk.attach/sun.tools.attach.HotSpotVirtualMachine.loadAgentLibrary(HotSpotVirtualMachine.java:119)
at jdk.attach/sun.tools.attach.HotSpotVirtualMachine.loadAgent(HotSpotVirtualMachine.java:147)
at com.taobao.arthas.core.Arthas.attachAgent(Arthas.java:122)
at com.taobao.arthas.core.Arthas.<init>(Arthas.java:27)
at com.taobao.arthas.core.Arthas.main(Arthas.java:151)
[ERROR] attach fail, targetPid: 77710
$ java -version
java version "13.0.2" 2020-01-14
Java(TM) SE Runtime Environment (build 13.0.2+8)
Java HotSpot(TM) 64-Bit Server VM (build 13.0.2+8, mixed mode, sharing)
然后我把JDK版本切换成jdk8,确实没问题了。为何会出现这个问题呢?是因为我Idea使用的是JDK8执行的。而iTerm最开始用的是JDK13,所以版本不一样,改一下则解决了问题。
|