Web应用线上诊断工具-Arthas
1. Arthas简介
-
Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。在线排查问题,无需重启;动态跟踪Java代码;实时监控JVM状态。
-
Arthas 支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。
2. 安装Arthas
2.1 Windows安装Arthas
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
## 注: 项目运行需要本地有启动的Java进程 若本地没有就会自动安装
2.2 Liunx下安装Arthas
与Windows安装大致相同
- Arthas目前支持Web Console,用户在attach成功之后,可以直接访问:http://127.0.0.1:8563。
- 默认只监听127.0.0.1 可以使用 -h 来查看命令
- eg: java -jar arthas-boot.jar --target-ip 192.168.2.100
2.3 卸载Arthas
2.3.1 Windows 卸载 Arthas
- Windows平台直接删除 user home下面的 .arthas 和logs/arthas目录
2.3.2 Liunx 卸载 Arthas
rm -rf ~/.arthas/
rm -rf ~/logs/arthas
3. Arthas命令
3.1 基础命令
3.1.1 help
- 可查看Arthas中有哪些可以使用的命令
3.1.2 cat
- 查看文件 与liunx别无二致
3.1.3 grep
- 过滤信息 与liunx一致
3.1.4 pwd
- 查看当前arthas 所在目录
3.1.5 cls
- 清屏
3.1.6 session
- 查看会话
3.1.7 reset
- 重置增强类将Arthas增强的类全部还原,服务端关闭也会重置
## 还原Test类
[arthas@29543]$ reset Test
## 还原以Test皆为的类
[arthas@29543]$ reset *Test
##还原所有类
[arthas@29543]$ reset
3.1.8 version
- 查看Arthas 版本
[arthas@29543]$ version
3.5.5
3.1.9 quit
- 退出当前客户端,其他客户端可以正常使用
3.1.10 stop
- 关闭Arthas 服务器
3.1.11 keymap
- Arthas快捷键列表及自定义快捷键
3.1.12 history
- 查看历史记录
3.1.13 exit
- 退出
3.2 JVM相关命令
3.2.1 dashboard仪表板
- cat jvm’s thread, memory, gc, vm, tomcat info.
[arthas@44774]$ dashboard
3.2.2 thread 线程
- 查看当前JVM的线程堆栈信息
参数名称 | 参数说明 |
---|---|
id | 线程id |
[n:] | 指定最忙的前N个线程并打印堆栈 |
[b] | 找出当前阻塞其他线程的线程 |
[i ] | 指定cpu使用率统计的采样间隔,单位为毫秒,默认值为200 |
[–all] | 显示所有匹配的线程 |
[arthas@44774]$ thread
[arthas@44774]$ thread -id(线程id)
#指定采样时间间隔,每隔1000ms采样 显示最占用时间的线程
[arthas@44774]$ thread -i 1000 -n 3
#查看WATING的线程
[arthas@44774]$ thread --state WATING
3.2.3 jvm
- 查看当前JVM信息
[arthas@29543]$ jvm
RUNTIME
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MACHINE-NAME 29543@honor
JVM-START-TIME 2022-01-10 10:29:20
MANAGEMENT-SPEC-VERSION 1.2
SPEC-NAME Java Virtual Machine Specification
SPEC-VENDOR Oracle Corporation
SPEC-VERSION 1.8
VM-NAME OpenJDK 64-Bit Server VM
VM-VENDOR Oracle Corporation
VM-VERSION 25.242-b08
INPUT-ARGUMENTS -Xms512m
-Xmx512m
CLASS-PATH /data/jar/ssl.jar
BOOT-CLASS-PATH /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64/jre/lib/resources.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_6
4/jre/lib/rt.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242
.b08-0.el7_7.x86_64/jre/lib/jsse.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64/jre/lib/jce.jar:/usr/lib/jvm/java-1.8.0-open
jdk-1.8.0.242.b08-0.el7_7.x86_64/jre/lib/charsets.jar:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64/jre/lib/jfr.jar:/usr/lib/jv
m/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64/jre/classes
LIBRARY-PATH /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CLASS-LOADING
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
LOADED-CLASS-COUNT 14803
TOTAL-LOADED-CLASS-COUNT 14804
UNLOADED-CLASS-COUNT 1
IS-VERBOSE false
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
COMPILATION
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NAME HotSpot 64-Bit Tiered Compilers
TOTAL-COMPILE-TIME 42647
[time (ms)]
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GARBAGE-COLLECTORS
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
PS Scavenge name : PS Scavenge
[count/time (ms)] collectionCount : 20
collectionTime : 238
PS MarkSweep name : PS MarkSweep
[count/time (ms)] collectionCount : 3
collectionTime : 348
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MEMORY-MANAGERS
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CodeCacheManager Code Cache
Metaspace Manager Metaspace
Compressed Class Space
PS Scavenge PS Eden Space
PS Survivor Space
PS MarkSweep PS Eden Space
PS Survivor Space
PS Old Gen
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MEMORY
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
HEAP-MEMORY-USAGE init : 536870912(512.0 MiB)
[memory in bytes] used : 116238736(110.9 MiB)
committed : 508559360(485.0 MiB)
max : 508559360(485.0 MiB)
NO-HEAP-MEMORY-USAGE init : 2555904(2.4 MiB)
[memory in bytes] used : 115122512(109.8 MiB)
committed : 118800384(113.3 MiB)
max : -1(-1 B)
PENDING-FINALIZE-COUNT 0
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OPERATING-SYSTEM
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OS Linux
ARCH amd64
PROCESSORS-COUNT 4
LOAD-AVERAGE 1.91
VERSION 3.10.0-1062.18.1.el7.x86_64
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
THREAD
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
COUNT 39
DAEMON-COUNT 34
PEAK-COUNT 39
STARTED-COUNT 50
DEADLOCK-COUNT 0
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
FILE-DESCRIPTOR
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MAX-FILE-DESCRIPTOR-COUNT 131072
OPEN-FILE-DESCRIPTOR-COUNT 122
-
THREAD相关
-
COUNT: JVM当前活跃的线程数
-
DAEMON-COUNT: JVM当前活跃的守护线程数
-
PEAK-COUNT: 从JVM启动开始曾经活着的最大线程数
-
STARTED-COUNT: 从JVM启动开始总共启动过的线程次数
-
DEADLOCK-COUNT: JVM当前死锁的线程数
-
-
文件描述符相关
-
MAX-FILE-DESCRIPTOR-COUNT:JVM进程最大可以打开的文件描述符数
-
OPEN-FILE-DESCRIPTOR-COUNT:JVM当前打开的文件描述符数
-
3.2.4 sysprop
- 查看和修改JVM系统属性
##查看单个属性
[arthas@29543]$ sysprop java.version
##修改单个属性
[arthas@29543]$ sysprop user.country
[arthas@29543]$ sysprop user.country CN
##查看所有属性
[arthas@29543]$ sysprop
3.2.5 sysenv
- 查看当前虚拟机环境属性
##查看所有环境变量
[arthas@29543]$ sysenv
## 查看单个环境变量
[arthas@29543]$ sysenv USER
3.2.6 vmoption
- 查看,更新VM诊断相关的参数
##查看全部
[arthas@29543]$ vmoption
KEY VALUE ORIGIN WRITEABLE
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
HeapDumpBeforeFullGC false DEFAULT true
HeapDumpAfterFullGC false DEFAULT true
HeapDumpOnOutOfMemoryError false DEFAULT true
HeapDumpPath DEFAULT true
CMSAbortablePrecleanWaitMillis 100 DEFAULT true
CMSWaitDuration 2000 DEFAULT true
CMSTriggerInterval -1 DEFAULT true
PrintGC false DEFAULT true
PrintGCDetails false DEFAULT true
PrintGCDateStamps false DEFAULT true
PrintGCTimeStamps false DEFAULT true
PrintGCID false DEFAULT true
PrintClassHistogramBeforeFullGC false DEFAULT true
PrintClassHistogramAfterFullGC false DEFAULT true
PrintClassHistogram false DEFAULT true
MinHeapFreeRatio 0 DEFAULT true
MaxHeapFreeRatio 100 DEFAULT true
PrintConcurrentLocks false DEFAULT true
##查看单个
[arthas@29543]$ vmoption PrintGCDetails
##修改对应参数值
[arthas@29543]$ vmoption PrintGCDetails true
3.2.7 getstatic
- 查看类的静态属性(推荐使用ognl)
[arthas@29543]$ getstatic San Random
3.2.8 ognl
- 执行Ognl 表达式
参数名称 | 参数说明 |
---|---|
express | 执行的表达式 |
[c:] | 执行表达式的 ClassLoader 的 hashcode,默认值是SystemClassLoader |
[classLoaderClass:] | 指定执行表达式的 ClassLoader 的 class name |
[x] | 结果对象的展开层次,默认值1 |
#调用静态函数
[arthas@29543]$ ognl '@java.lang.System@out.println("hello")'
null
#执行多行表达式,赋值给临时变量,返回一个List:
[arthas@29543]$ ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}'
@ArrayList[
@String[/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64/jre],
@String[OpenJDK Runtime Environment],
]
# 获取ClassLoader列表
[arthas@29543]$ classloader -t
+-BootstrapClassLoader
+-sun.misc.Launcher$ExtClassLoader@b81eda8
+-com.taobao.arthas.agent.ArthasClassloader@3c0ff9ae
+-com.taobao.arthas.agent.ArthasClassloader@d70e974
+-sun.misc.Launcher$AppClassLoader@70dea4e
+-org.springframework.boot.loader.LaunchedURLClassLoader@49c2faae
Affect(row-cnt:6) cost in 26 ms.
#通过hashCode 指定ClassLoader
[arthas@29543]$ ognl -c 49c2faae
3.3 class/classloader 相关命令
3.3.1 sc
- 查看JVM已加载的类信息
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 方法名表达式匹配 |
[d] | 输出当前类的详细信息,包括这个类所加载的原始文件来源、类的声明、加载的ClassLoader等详细信息。如果一个类被多个ClassLoader所加载,则会出现多次 |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[f] | 输出当前类的成员变量信息(需要配合参数-d一起使用) |
[x:] | 指定输出静态变量时属性的遍历深度,默认为 0,即直接使用 toString 输出 |
[c:] | 指定class的 ClassLoader 的 hashcode |
[classLoaderClass:] | 指定执行表达式的 ClassLoader 的 class name |
[n:] | 具有详细信息的匹配类的最大数量(默认为100) |
#匹配san下所有的类
[arthas@29543]$ sc com.san.*
#打印类的详细信息
[arthas@29543]$ sc -d com.san.vo.UserDTO
#打印类的Field信息
[arthas@29543]$ sc -d -f com.san.vo.UserDTO
3.3.2 sm
- 查看已加载类的方法信息
参数名称 参数说明
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 方法名表达式匹配 |
[d] | 展示每个方法的详细信息 |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[c:] | 指定class的 ClassLoader 的 hashcode |
[classLoaderClass:] | 指定执行表达式的 ClassLoader 的 class name |
[n:] | 具有详细信息的匹配类的最大数量(默认为100) |
[arthas@29543]$ sm -d java.lang.String toString
declaring-class java.lang.String
method-name toString
modifier public
annotation
parameters
return java.lang.String
exceptions
classLoaderHash null
3.3.3 jad
- 反编译
[arthas@44774]$ jad com.xcc.config.CorsConfig
- ClassLoader 扩展类加载器
- Location 定位到响应的jar
3.3.4 mc
- Memory Compiler/内存编译器,编译.java文件生成.class。
- 可以通过 -c或者- -classLpaderClass来指定ClassLoader
[arthas@44774]$ mc /tmp/Test.java
#通过-c 指定ClassLoader
[arthas@44774]$ mc -c 327a647b /tmp/Test.java
#通过-- classLoaderClass 指定ClassLoader
[arthas@44774]$ mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /tmp/UserController.java -d /tmp
#通过-d指定输出目录
[arthas@44774]$ mc -d /tmp/output /tmp/ClassA.java /tmp/ClassB.java
3.3.5 redefine
- 加载外部的.class文件,redefine jvm已加载的类。(推荐使用retransform)
- 可以使用-c 或者- -classLoaderClass
[arthas@44774]$ redefine /tmp/Test.class
[arthas@44774]$ redefine -c 327a647b /tmp/Test.class /tmp/Test\$Inner.class
[arthas@44774]$ redefine --classLoaderClass sun.misc.Launcher$AppClassLoader /tmp/Test.class /tmp/Test\$Inner.class
3.3.5.1 redefine限制
- 不允许新增加field/method
- 正在跑的函数,没有退出不能生效,比如下面新增加的System.out.println,只有run()函数里的会生效
public class MathGame {
public static void main(String[] args) throws InterruptedException {
MathGame game = new MathGame();
while (true) {
game.run();
TimeUnit.SECONDS.sleep(1);
// 这个不生效,因为代码一直跑在 while里
System.out.println("in loop");
}
}
public void run() throws InterruptedException {
// 这个生效,因为run()函数每次都可以完整结束
System.out.println("call run()");
try {
int number = random.nextInt();
List<Integer> primeFactors = primeFactors(number);
print(number, primeFactors);
} catch (Exception e) {
System.out.println(String.format("illegalArgumentCount:%3d, ", illegalArgumentCount) + e.getMessage());
}
}
3.3.5.2 常见问题
-
redefine的class不能修改、添加、删除类的field和method,包括方法参数、方法名称及返回值
-
如果mc失败,可以在本地开发环境编译好class文件,上传到目标系统,使用redefine热加载class
-
目前redefine 和watch/trace/jad/tt等命令冲突
-
reset命令对redefine的类无效。如果想重置,需要redefine原始的字节码。
-
redefine后的原来的类不能恢复,redefine有可能失败(比如增加了新的field),参考jdk本身的文档。
3.3.6 retransform
- 加载外部的.class文件,retransform jvm已加载的类。
- 可以使用-c 或者- -classLoaderClass
#查看
[arthas@44774]$ retransform -l
#删除指定id
[arthas@44774]$ retransform -d 1
#删除所有
[arthas@44774]$ retransform --deleteAll
#显式触发
[arthas@44774]$ retransform --classPattern demo.*
[arthas@44774]$ retransform -c 327a647b /tmp/Test.class /tmp/Test\$Inner.class
[arthas@44774]$ retransform --classLoaderClass 'sun.misc.Launcher$AppClassLoader' /tmp/Test.class
- 注 :如果想要消除retransform 需要
删除这个类对应的retransform entry
并重新触发
retransform - retransform的限制与redefine相同
3.3.7 dump
- dump 已加载类的 bytecode(字节码文件)保存到特定目录
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
[c:] | 类所属 ClassLoader 的 hashcode |
[classLoaderClass:] | 指定执行表达式的 ClassLoader 的 class name |
[d:] | 设置类文件的目标目录 |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[arthas@29543]$ dump java.lang.String
HASHCODE CLASSLOADER LOCATION
null /root/logs/arthas/classdump/java/lang/String.class
3.3.8 classloader
- 查看classloader的继承树,urls,类加载信息
参数名称 | 参数说明 |
---|---|
[l] | 按类加载实例进行统计 |
[t] | 打印所有ClassLoader的继承树 |
[a] | 列出所有ClassLoader加载的类,请谨慎使用 |
[c:] | ClassLoader的hashcode |
[classLoaderClass:] | 指定执行表达式的 ClassLoader 的 class name |
[c: r:] | 用ClassLoader去查找resource |
[c: load:] | 用ClassLoader去加载指定的类 |
[arthas@29543]$ classloader
name numberOfInstances loadedCountTotal
org.springframework.boot.loader.LaunchedURLClassLoader 1 12154
BootstrapClassLoader 1 4514
com.taobao.arthas.agent.ArthasClassloader 2 2929
sun.reflect.DelegatingClassLoader 785 785
sun.misc.Launcher$ExtClassLoader 1 65
sun.misc.Launcher$AppClassLoader 1 47
com.alibaba.fastjson.util.ASMClassLoader 2 15
org.apache.cxf.common.util.ASMHelper$TypeHelperClassLoader 1 6
java.net.URLClassLoader 1 1
org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader 1 0
3.3.9 monitor
描述:方法执行监控,monitor 命令是一个非实时返回命令.
- 监控的维度说明
监控项 | 说明 |
---|---|
timestamp | 时间戳 |
class | Java类 |
method | 方法(构造方法、普通方法) |
total | 调用次数 |
success | 成功次数 |
fail | 失败次数 |
rt | 平均RT |
fail-rate | 失败率 |
- 参数说明
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 方法名表达式匹配 |
condition-express | 条件表达式 |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[c:] | 统计周期,默认值为120秒 |
[b] | 在方法调用之前计算condition-express |
##五秒监控一次
arthas@29543]$ monitor -c 5 com.xcc.controller.system.UserInfoController getSales
Press Q or Ctrl+C to abort.
Affect(class count: 2 , method count: 2) cost in 195 ms, listenerId: 3
timestamp class method total success fail avg-rt(ms) fail-rate
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2022-01-12 16:33:09 com.xcc.controller.system.UserInfoController getSales 1 1 0 4.00 0.00%
$$EnhancerBySpringCGLIB$$dfa27ce
2022-01-12 16:33:09 com.xcc.controller.system.UserInfoController getSales 1 1 0 3.58 0.00%
3.3.10 watch
3.3.11 trace
3.3.12 stack
3.3.13 tt
本文作者:张三Blog
本文链接:https://www.cnblogs.com/zhangsan-plus/p/16503253.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步