快速入门
简介
Arthas 是Alibaba开源的Java诊断工具。安装在系统所在服务器。可以帮助开发人员或者运维人员查找问题,分析性能,bug追踪。
使用场景
- 快速 debug,最常见的是遇到 bug但没有打印相应的日志(入参、返回值),如果是生产或者预发环境,重新打补丁部署很麻烦
- 反编译源码,查看 jvm 加载的代码是否符合预期
- 耗时分析,查看方法内调用路径及各方法执行耗时情况
- 查看 JVM 运行情况
等等......
基本流程
这里只记录基本操作流程,详细可以看官方文档
下载
curl -O https://arthas.aliyun.com/arthas-boot.jar
启动
java -jar arthas-boot.jar
执行命令后,输入对应的Java应用编号,如下只有一个应用,输入编号:1
常用命令
dashboard
查看当前线程有哪些
dashboard
dashboard 每个几秒会刷新一次页面,展示不同的线程信息,主线程 main ID 一般为1。
线程相关线程id线程名线程组线程优先级线程状态CPU使用占比运行增量时间运行总时间中断位状态是否守护线程IDNAMEGROUPPRIORITYSTATE%CPUDELTA_TIMETIMEINTERRUPTEDAEMON298Tair-ClientTimeoutTaskProcessTimmain5TIMED_WAIT0.00.0002:41.879falsetrue356sentinel-time-tick-threadmain5TIMED_WAIT0.00.0002:31.821falsetrue354sentinel-container-system-metric-cmain5TIMED_WAIT0.00.0001:38.932falsetrue-1C2CompilerThread1--1-0.00.0000:58.318falsetrue-1C2CompilerThread0--1-0.00.0000:54.382falsetrue117metrics-RollingFileAppender-threadmain5TIMED_WAIT0.00.0000:40.750falsetrue118metrics-bin-reporter-1-thread-1main5TIMED_WAIT0.00.0000:39.405falsetrue282com.taobao.diamond.client.Worker.rmain5TIMED_WAIT0.00.0000:38.785falsetrue422com.taobao.diamond.client.Worker.lmain5TIMED_WAIT0.00.0000:38.589falsetrue114com.taobao.diamond.client.Worker.dmain5TIMED_WAIT0.00.0000:38.276falsetrue-1VMThread--1-0.00.0000:34.080falsetrue内存相关MemoryusedtotalmaxusageGC(堆)(垃圾回收次数)heap585M3925M3925M14.91%gc.parnew.count58(伊甸园区)(垃圾回收耗时)par_eden_space428M1706M1706M25.12%gc.parnew.time(ms) 2016(幸存者区)(标记清除算法次数)par_survivor_space19M170M170M11.71%gc.concurrentmarksweep.count0(老年代)(标记清除算法耗时)cms_old_gen136M2048M2048M6.66%gc.concurrentmarksweep.time(ms) 0(非堆)nonheap391M398M1256M31.14%(代码缓存区)code_cache100M101M240M41.90%(元空间)metaspace258M262M512M50.43%(压缩空间)compressed_class_space32M33M504M6.43%(直接内存)direct4M4M-100.00%运行情况RuntimeTomcatos.nameLinuxconnectorhttp-nio-7002os.version4.9.151-015.ali3000.alios7.x86_64QPSNaNjava.version1.8.0_242RT(ms) 0.31java.home/opt/taobao/install/ajdk/jreerror/sNaNsystemload.average0.00received/s0Bprocessors4sent/s0Btimestamp/uptimeconnectorhttp-nio-7001QPS-19461.00RT(ms) 184.00数据说明ID: Java级别的线程ID,注意这个ID不能跟jstack中的nativeID一一对应。NAME: 线程名GROUP: 线程组名PRIORITY: 线程优先级, 1~10之间的数字,越大表示优先级越高STATE: 线程的状态CPU%: 线程的cpu使用率。比如采样间隔1000ms,某个线程的增量cpu时间为100ms,则cpu使用率=100/1000=10%DELTA_TIME: 上次采样之后线程运行增量CPU时间,数据格式为秒TIME: 线程运行总CPU时间,数据格式为分:秒INTERRUPTED: 线程当前的中断位状态DAEMON: 是否是daemon线程
thread
打印线程堆栈信息,可以使用 grep 过滤。
thread 1 | grep 'main('
jad
反编译 Java class
jad xx.xx.ClassName
watch
观察到指定函数的调用情况。能观察到的范围为:返回值、抛出异常、入参
watch xx.ClassName method -x 4 {params,target,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 辅助判断标记,当前的方法调用以正常返回的形式结束。
trace
方法内部调用路径,并输出方法路径上的每个节点上耗时
trace xx.ClassName method
- 次数限制。如果方法调用次数很多,可以用 -n 指定捕捉结果的次数
- 捕捉10次:trace xx.ClassName method -n 10
- 打印JDK函数。默认情况下trace不会包含JDK里的函数调用
- trace --skipJDKMethod false xx.ClassName method
- 耗时过滤。如果方法本身的耗时满足要求则打印具体的调用链路,如果不满足则什么都不打印
- trace xx.ClassName method '#cost > 10'
- trace多个类/函数。trace命令只会trace匹配到的函数里的子调用,并不会向下trace多层。因为trace是代价比较贵的,多层trace可能会导致最终要trace的类和函数非常多。
- trace -E com.test.ClassA|org.test.ClassB method1|method2|method3
sc
查看 JVM 已加载的类信息。
sc -d xx.ClassName
-d 输出当前类的详细信息,包括这个类所加载的原始文件来源、类的声明、加载的ClassLoader等详细信息。
如果一个类被多个ClassLoader所加载,则会出现多次。
class-info com.alibaba.logistics.mirror.charge.start.Application
code-source /home/admin/logistics-mirror-charge/target/logistics-mirror-charge/BOOT-INF/classes/
name com.alibaba.logistics.mirror.charge.start.Application
isInterface false
isAnnotation false
isEnum false
isAnonymousClass false
isArray false
isLocalClass false
isMemberClass false
isPrimitive false
isSynthetic false
simple-name Application
modifier public
annotation org.springframework.context.annotation.Import,org.springframework.boot.autoconfigure.SpringBootApplication,org.springfram
ework.context.annotation.ImportResource
interfaces
super-class +-java.lang.Object
class-loader +-com.taobao.pandora.boot.loader.LaunchedURLClassLoader@f8908f6
+-sun.misc.Launcher$AppClassLoader@18b4aac2
+-sun.misc.Launcher$ExtClassLoader@5a18cd76
classLoaderHash f8908f6
class-info com.alibaba.logistics.mirror.charge.start.Application$$EnhancerBySpringCGLIB$$1ed3c95
code-source /home/admin/logistics-mirror-charge/target/logistics-mirror-charge/BOOT-INF/classes/
name com.alibaba.logistics.mirror.charge.start.Application$$EnhancerBySpringCGLIB$$1ed3c95
isInterface false
isAnnotation false
isEnum false
isAnonymousClass false
isArray false
isLocalClass false
isMemberClass false
isPrimitive false
isSynthetic false
simple-name Application$$EnhancerBySpringCGLIB$$1ed3c95
modifier public
annotation
interfaces org.springframework.context.annotation.ConfigurationClassEnhancer$EnhancedConfiguration
super-class +-com.alibaba.logistics.mirror.charge.start.Application
+-java.lang.Object
class-loader +-com.taobao.pandora.boot.loader.LaunchedURLClassLoader@f8908f6
+-sun.misc.Launcher$AppClassLoader@18b4aac2
+-sun.misc.Launcher$ExtClassLoader@5a18cd76
classLoaderHash f8908f6
Affect(row-cnt:2) cost in 43 ms.
退出
quit —— 退出当前 Arthas 客户端,其他 Arthas 客户端不受影响
shutdown —— 关闭 Arthas 服务端,所有 Arthas 客户端全部退出 & 重置所有增强过的类,就不用单独调用reset
原理介绍
JVM - attach
JVM Attach机制实现:
http://lovestblog.cn/blog/2014/06/18/jvm-attach/?spm=ata.21736010.0.0.3c9a75360Zl0xR
Agent & Instrumentation
JAVA SE 6新特性:Instrumentation:
https://blog.csdn.net/m0_37556444/article/details/106379314
arthas流程