以下内容【来源于官网】加上自己遇到的问题
- 先启动待排查的java项目(线上在运行的项目可忽略此步骤)
以下2、3步骤和4根据情况选其一即可
- 下载arthas并启动
# 下载
wget https://arthas.aliyun.com/arthas-boot.jar
# 运行 --target-ip 0.0.0.0参数可选
java -jar arthas-boot.jar --target-ip 0.0.0.0
- sarthas-boot是Arthas的启动程序,它启动后,会列出所有的Java进程,用户可以选择需要诊断的目标进程。
- 如果项目是运行在docker中的,可以这样安装运行arthas-boot
# docker ps查找容器id
docker ps
docker exec -it ${containerId} /bin/bash -c "wget https://arthas.aliyun.com/arthas-boot.jar && java -jar arthas-boot.jar"
- 选择第一个进程,输入
1
,再Enter/回车
进入主题前,先了解下arthas指令的小建议:
- help帮助指令
Arthas里每一个命令都有详细的帮助信息。可以用-h来查看。帮助信息里有EXAMPLES和WIKI链接。
比如:sysprop -h
-
自动补全
Arthas支持丰富的自动补全功能,在使用有疑惑时,可以输入Tab来获取更多信息。
比如输入 sysprop java. 之后,再输入Tab,会补全出对应的key:$ sysprop java. java.runtime.name java.protocol.handler.pkgs java.vm.version java.vm.vendor java.vendor.url java.vm.name ...
-
readline的快捷键支持
Arthas支持常见的命令行快捷键,比如Ctrl + A跳转行首,Ctrl + E跳转行尾。
更多的快捷键可以用 keymap 命令查看。 -
历史命令的补全
如果想再执行之前的命令,可以在输入一半时,按Up/↑ 或者 Ddown/↓,来匹配到之前的命令。
比如之前执行过sysprop java.version,那么在输入sysprop ja之后,可以输入Up/↑,就会自动补全为sysprop java.version。 -
如果想查看所有的历史命令,也可以通过 history 命令查看到。
-
pipeline
Arthas支持在pipeline之后,执行一些简单的命令,比如:
sysprop | grep java
sysprop | wc -l -
查看JVM信息
-
sysprop
- sysprop 可以打印所有的System Properties信息。
- 也可以指定单个key: sysprop java.version
- 也可以通过grep来过滤: sysprop | grep user
- 可以设置新的value: sysprop testKey testValue
-
sysenv
sysenv 命令可以获取到环境变量。和sysprop命令类似。 -
jvm
jvm 命令会打印出JVM的各种详细信息。 -
dashboard
dashboard 命令可以查看当前系统的实时数据面板。
- sc/sm 查看已加载的类
-
sc
sc 命令可以查找到所有JVM已经加载到的类。
如果搜索的是接口,还会搜索所有的实现类。比如查看所有的Filter实现类:
sc javax.servlet.Filter
通过-d参数,可以打印出类加载的具体信息,很方便查找类加载问题。
sc -d javax.servlet.Filter
sc支持通配,比如搜索所有的StringUtils:
sc *StringUtils
-
sm
sm命令则是查找类的具体函数。比如:
sm java.math.RoundingMode
通过-d参数可以打印函数的具体属性:
sm -d java.math.RoundingMode
也可以查找特定的函数,比如查找构造函数:
sm java.math.RoundingMode <init>
-
jad
可以通过 jad 命令来反编译代码:
jad com.example.demo.arthas.user.UserController
通过–source-only参数可以只打印出 反编译的源代码:
jad --source-only com.example.demo.arthas.user.UserController
-
- ognl
在Arthas里,有一个单独的ognl命令,可以动态执行代码。- 调用static函数
ognl '@java.lang.System@out.println("hello ognl")'
- 查找类的ClassLoader
输出sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash
classLoaderHash 1be6f5c3
注意hashcode是变化的,需要先查看当前的ClassLoader信息,提取对应ClassLoader的hashcode。 - 可以手动指定hashcode值,格式:ognl -c
$ ognl -c 1be6f5c3 @com.example.demo.arthas.user.UserController@logger
- 对于只有唯一实例的ClassLoader可以通过–classLoaderClass指定class name,使用起来更加方便:
–classLoaderClass 的值是ClassLoader的类名,只有匹配到唯一的ClassLoader实例时才能工作,目的是方便输入通用命令,而-c 是动态变化的。$ ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader @org.springframework.boot.SpringApplication@logger@Slf4jLocationAwareLog [FQCN=@String[org.apache.commons.logging.LogAdapter$Slf4jLocationAwareLog], name=@String[org.springframework.boot.SpringApplication], logger=@Logger[Logger[org.springframework.boot.SpringApplication]],]
- 获取静态类的静态字段
示例:- 获取UserController类里的logger字段:
ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader @com.example.demo.arthas.user.UserController@logger
- 还可以通过-x参数控制返回值的展开层数。比如:
ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader -x 2 @com.example.demo.arthas.user.UserController@logger
- 获取UserController类里的logger字段:
- 执行多行表达式,赋值给临时变量,返回一个List
$ ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}' @ArrayList[ @String[/Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home/jre], @String[Java(TM) SE Runtime Environment],]
在Arthas里ognl表达式是很重要的功能,在很多命令里都可以使用ognl表达式。 一些更复杂的用法,可以参考: OGNL特殊用法请参考:https://github.com/alibaba/arthas/issues/71 OGNL表达式官方指南:https://commons.apache.org/proper/commons-ognl/language-guide.html
- 调用static函数