Arthas

Alibaba开源的Java诊断工具Arthas(阿尔萨斯)

Why use Arthas?

这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
改的代码为什么没有执行到?难道是没 commit?分支搞错了?
遇到问题无法在预发 debug 一下,难道只能通过加日志再重新预发布吗?
线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现,怎么办?
是否有一个全局视角来查看系统的运行状况?
有什么办法可以监控到容器和中间件的实时运行状态?

What is Arthas?

Arthas 是基于 Greys 进行二次开发的全新在线诊断工具,利用Java6的Instrumentation特性,动态增强你所指定的类,获取你想要到的信息, 采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,让你在定位、分析诊断问题时看每一个操作都看起来是那么的 666.

1.官网地址:
安装
自动安装:
Arthas 支持在 Linux/Unix/Mac 等平台上一键安装,
命令行 curl -L https://alibaba.github.io/arthas/install.sh | sh 回车
启动Arthas: ./as.sh ./install-local.sh

2.基本使用

win+R—>cmd—>telnet 127.0.0.1 3658(netstat show port)
Windows系统:cd 到解压的arthas目录下执行jps(pid jps)
1.as.bat pid启动arthas
2.java -jar arthas-demo.jar
3.java -jar arthas-boot.jar
基础命令
help——查看命令帮助信息
cls——清空当前屏幕区域
session——查看当前会话的信息
version——输出当前目标 Java 进程所加载的 Arthas 版本号
keymap——Arthas快捷键列表及自定义快捷键
quit——退出当前 Arthas 客户端,其他 Arthas 客户端不受影响
shutdown——关闭 Arthas 服务端,所有 Arthas 客户端全部退出
reset——重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类

jvm
dashboard–当前系统的实时数据面板
thread–查看当前 JVM 的线程堆栈信息
jvm–查看当前 JVM 的信息

3.Command

1) dashboard–当前系统的实时数据面板,Ctrl+C退出
dashboard
ID: JVM thread ID, pls. note this ID is different from the nativeID in jstack
NAME: thread name
GROUP: thread group name
PRIORITY: thread priority, ranged from 1 to 10. The greater number, the higher priority
STATE: thread state
线程共包括以下5种状态:
1.初始状态(New) :线程对象被创建后,就进入了新建状态。
2.就绪状态(Runnable): 也被称为“可执行状态”。
3. 运行状态(Running) : 线程只能从就绪状态进入到运行状态。
4. 阻塞状态(Blocked) : 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。(等待(WAITING))
5. 死亡状态(Dead) :线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
CPU%: the ratio of CPU usage for the thread, sampled every 100ms
TIME: total running time in minute:second format
INTERRUPTED: the thread interruption state
DAEMON: daemon thread or not
2)thread–查看当前 JVM 的线程堆栈信息
2.1)thread:List all threads’ info when no options provided
2.2)thread -n 3:List the top n busiest threads with detailed stack trace
2.3)thread id: show the running stack for the target thread
2.4)thread -b: locate the thread bocking the others.
Note: By now Arthas only supports to locate the thread blocked by synchronzied, while java.util.concurrent.Lock is not supported yet.
2.5)thread -i: specify the sampling interval
thread -n 3 -i 1000
3.jvm:查看当前 JVM 的信息
Thread related:
COUNT: the count of active threads
DAEMON-COUNT: the count of active daemon threads
PEAK-COUNT: the maximum count of the live threads since JVM starts
STARTED-COUNT: the total count of the created threads since JVM starts
DEADLOCK-COUNT: the count of deadlocked threads

File descriptor related:
MAX-FILE-DESCRIPTOR-COUNT:the count of max file descriptor JVM process can open
OPEN-FILE-DESCRIPTOR-COUNT:the current count of file descriptor JVM process open
4.sysprop:Examine the system properties from the target JVM(key-value fromat)
USAGE:sysprop [-h] [property-name] [property-value]
sysprop:show all
sysprop tab:show all propNames
sysprop propName: propName=propValue
Sysprop propName newPropValue:Modify Single Property
5.sysenv:View the current JVM environment variables.
1)sysenv:View all environment variables(key-value)
2)sysenv tab for auto-completion
3)sysenv propName:propName=propValue(command and propName case-sensitive)
6.getstatic:It is recommended to use the [OGNL] (ognl.md) command, which will be more flexibility.
7.Ognl?

1)Call static method: ognl ‘@java.lang.System@out.println(“hello”)’
2)Call static field:’@demo.MathGame@random’
3)Execute a multi-line expression, and return a list:
ognl ‘#value1=@System@getProperty(“java.home”), #value2=@System@getProperty(“java.runtime.name”), {#value1, #value2}’
8.sc:Search classes loaded by JVM.

9.sm 查看已加载类的方法信息,sm 命令只能看到由当前类所声明 (declaring) 的方法,父类则无法看到。
e.g sm java.lang.String
sm -d java.lang.String toString
参数名称 参数说明
class-pattern 类名表达式匹配
method-pattern 方法名表达式匹配
[d] 展示每个方法的详细信息
[E] 开启正则表达式匹配,默认为通配符匹配
10.dump 已加载类的 bytecode 到特定目录
参数名称 参数说明
class-pattern 类名表达式匹配
[c:] 类所属 ClassLoader 的 hashcode
[E] 开启正则表达式匹配,默认为通配符匹配
e.g dump java.lang.String
11.jad反编译指定已加载类的源码,反编绎时只显示源代码
jad 命令将 JVM 中实际运行的 class 的 byte code 反编译成 java 代码,便于理解业务逻辑;
不过,反编译出来的 java 代码可能会存在语法错误,但不影响阅读理解。
e.g jad java.lang.String
1)默认情况下,反编译结果里会带有ClassLoader信息,通过–source-only选项,可以只打印源代码。
jad --source-only packageName.className
2)反编译指定函数:jad packageName.className methodName
3)反编译时指定ClassLoader
当有多个 ClassLoader 都加载了这个类时,jad 命令会输出对应 ClassLoader 实例的 hashcode,然后只需要重新执行 jad 命令,并使用参数 -c 就可以反编译指定 ClassLoader 加载的那个类了;
jad packageName.className -c hashcode
12.classloader:查看classloader的继承树,urls,类加载信息
1)classloader:按类加载类型查看统计信息
2)classloader -1:按类加载实例查看统计信息
3)classloader -t:查看ClassLoader的继承树
4)classloader -c 3d4eac69(classloader -t中拼接在@之后的hashcode):查看URLClassLoader实际的urls
5)classloader -c 3d4eac69 -r META-INF/MANIFEST.MF:使用ClassLoader去查找resource
6)classloader -c 1b6d3586 -r java/lang/String.class:也可以尝试查找类的class文件
7)classloader -c 3d4eac69 --load demo.MathGame:使用ClassLoader去加载类
13.mc : memory Compiler/内存编译器,编译.java文件生成.class。
e.g /exercise/Demo.java
1)可以通过-c参数指定classloader
e.g mc -c 3242456b /exercise/Demo.java
2)可以通过-d命令指定输出目录
mc -d /exercise/output /tmp/ClassA.java /tmp/ClassB.java
注意,mc命令有可能失败。如果编译失败可以在本地编译好.class文件,再上传到服务器。
14.redefine:加载外部的.class文件,redefine jvm已加载的类。
1)jad命令反编译,然后可以用其它编译器,比如vim来修改源码
2)mc命令来内存编译修改过的代码
3)用redefine命令加载新的字节码
注意, redefine后的原来的类不能恢复,redefine有可能失败(比如增加了新的field).
可以在本地修改代码,编译好后再上传到服务器上,有的服务器不允许直接上传文件,可以使用base64命令来绕过。
a)在本地先转换.class文件为base64,再保存为result.txt
base64 <Demo.class> result.txt
b)到服务器上,新建并编辑result.txt,复制本地的内容,粘贴再保存。
c)把服务器上的result.txt还原为.class
base64 -d < result.txt > Test.class
d)用md5命令计算哈希值,校验是否一致.
redefine的限制:
1)不允许新增加field/method.
2)正在跑的函数,没有退出不能生效.
15.monitor:对匹配 class-pattern/method-pattern的类、方法的调用进行监控
monitor命令是一个非实时返回命令(不断的等待目标 Java 进程返回信息,直到用户输入 Ctrl+C 为止)
监控的维度说明:
监控项 说明
timestamp 时间戳
class Java类
method 方法(构造方法、普通方法)
total 调用次数
success 成功次数
fail 失败次数
rt 平均RT
fail-rate 失败率

参数说明:
方法拥有一个命名参数 [c:],意思是统计周期(cycle of output),拥有一个整型的参数值,统计周期,默认值为120秒。
16. watch:指定方法执行数据观测,能观察到的范围为:返回值、抛出异常、入参,通过编写 OGNL 表达式进行对应变量的查看。
参数说明
watch 的参数比较多,主要是因为它能在 4 个不同的场景观察对象
参数名称 参数说明
class-pattern 类名表达式匹配
method-pattern 方法名表达式匹配
express 观察表达式
condition-express 条件表达式
[b] 在方法调用之前观察
[e] 在方法异常之后观察
[s] 在方法返回之后观察
[f] 在方法结束之后(正常返回和异常返回)观察
[E] 开启正则表达式匹配,默认为通配符匹配
[x:] 指定输出结果的属性遍历深度,默认为 1

1)watch 命令定义了4个观察事件点,即 -b 方法调用前,-e 方法异常后,-s 方法返回后,-f 方法结束后
2)4个观察事件点 -b、-e、-s 默认关闭,-f 默认打开,当指定观察点被打开后,在相应事件点会对观察表达式进行求值并输出
3)这里要注意方法入参和方法出参的区别,有可能在中间被修改导致前后不一致,除了 -b 事件点 params 代表方法入参外,其余事件都代表方法出参。
4)当使用 -b 时,由于观察事件点是在方法调用前,此时返回值或异常均不存在
16. trace:方法内部调用路径,并输出方法路径上的每个节点耗时
[n:] 命令执行次数
#cost 方法执行耗时
trace StringUtils isBlank '#cost>100’表示当执行时间超过100ms的时候,才会输出trace的结果。
注意事项:
trace 能方便的帮助定位和发现因 RT 高而导致的性能问题缺陷,但其每次只能跟踪一级方法的调用链路。
1)trace函数:trace demo.MathGame run
2)过滤掉jdk的函数:trace -j demo.MathGame run
-j: jdkMethodSkip, skip jdk method trace
3)据调用耗时过滤:trace demo.MathGame run ‘#cost > 10’
4)[12.033735ms] 的含义,12.033735 的含义是:当前节点在当前步骤的耗时,单位为毫秒
5)[0,0,0ms,11]xxx:yyy() [throws Exception],对该方法中相同的方法调用进行了合并,0,0,0ms,11 表示方法调用耗时,min,max,total,count;throws Exception 表明该方法调用中存在异常返回.
6)trace命令只会trace匹配到的函数里的子调用,并不会向下trace多层。因为trace是代价比较贵,不过可以用正则表匹配路径上的多个类和函数,一定程度上达到多层trace的效果。
trace -E com.test.ClassA|org.test.ClassB method1|method2|method3
17.stack:输出当前方法被调用的调用路径
1)stack packageName.className methodName(Press Ctrl+C to abort)
2)根据条件表达式来过滤:
stack packageName.className methodName ‘params[0]<0’ -n 2
3)根据执行时间来过滤
stack packageName.className methodName ‘#cost>5’
18.tt:方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能核对这些不同的时间下调用进行观测。
1)记录调用:记录当前方法的每次调用环境现场。
tt -t packageName.className methodName
1)命令参数:-t 记录类
Test的print方法的每次执行情况。
2)若遇到调用量大的方法时可以通过-n 3 指定需要记录的次数,当达到记录次数 的时Arthas会主动中断tt命令的记录过程,避免人工操作无法停止,将JVM内存撑爆。

2)表格字段说明
表格字段 字段解释
INDEX 时间片段记录编号,每一个编号代表着一次调用,tt很多命令都是基于此编号指定记录操作,非常重要。
TIMESTAMP 方法执行的本机时间,记录了这个时间片段所发生的本机时间
COST(ms) 方法执行的耗时
IS-RET 方法是否以正常返回的形式结束
IS-EXP 方法是否以抛异常的形式结束
OBJECT 执行对象的hashCode(),但不是对象在JVM中的内存地址。能帮助简单的标记当前执行方法的类实体
CLASS 执行的类名
METHOD 执行的方法名
3)解决方法重载:tt -t *Test print params.length1
通过指定参数个数的类型解决不同的方法签名,如果参数个数一样,你还可以这样写tt -t *Test print ‘params[1] instanceof Integer’
4)解决指定参数:tt -t *Test print params[0].mobile
"17521590358"
5)筛选出 具体某 方法的调用信息:tt -s ‘method.name==“methodName”’
6)查看调用信息:对于具体一个时间片的信息而言,可以通过 -i 参数后边跟着对 应的 INDEX 编号查看到他的详细信息。tt -i indexId
7)重做一次调用:通过 --replay-times 指定调用次数,通过 --replay-interval 指定多次调用间隔(单位ms, 默认1000ms),e.g tt -i 1004 -p
8)tt 命令是将当前环境的对象引用保存起来,但仅仅也只能保存一个引用而已。如果方法内部对入参进行了变更,或者返回的对象经过了后续的处理,那么在 tt 查看的时候将无法看到当时最准确的值。这也是为什么 watch 命令存在的意义。
19.cat :打印文件内容
20.pwd :返回当前的工作目录
21.option : 全局开关
想打开执行结果存日志功能,输入如下命令即可:options save-result true
结果会异步保存在:{user.home}/logs/arthas-cache/result.log,请定期进行清理,以免占据磁盘空间
使用新版本Arthas的异步后台任务将结果存日志文件:trace Test t >> &
此时命令会在后台异步执行,并将结果异步保存在文件(~/logs/arthas-cache/ P I D / {PID}/ PID/{JobId})中;此时任务的执行不受session断开的影响;任务默认超时时间是1天,可以通过全局 options 命令修改默认超时时间;此命令的结果将异步输出到文件中;此时不管 save-result 是否为true,都不会再往~/logs/arthas-cache/result.log 中异步写结果

Arthas异步调用:

1.可以执行jobs命令查看当前有哪些arthas任务在执行 :jobs
[id]*,*表示此job是当前session创建
timeout date是超时的时间,到这个时间,任务将会自动超时退出
2.使用&在后台执行任务,这时命令在后台执行,可以在console中继续执行其他命令。
trace Test t &
3. ‘ctrl + z’:将任务暂停。通过jbos查看任务状态将会变为Stopped,通过bg 或者fg 可让任务重新开始执行
‘ctrl + c’:停止任务
‘ctrl + d’:目前arthas中是空实现,不处理
4.1)任务在后台执行或者暂停状态(ctrl + z暂停任务)时,执行fg 将可以把对应的任务转到前台继续执行。在前台执行时,无法在console中执行其他命令.
2)当任务处于暂停状态时(ctrl + z暂停任务),执行bg 将可以把对应的任务在后台继续执行.
3)非当前session创建的job,只能由当前session fg到前台执行.
5.任务输出重定向:可通过>或者>>将任务输出结果输出到指定的文件中,可以和&一起使用,实现arthas命令的异步调用。
e.g trace Test t >> test.out &
6.当连接到远程的arthas server时,可能无法查看远程机器的文件,arthas同时支持了自动重定向到本地缓存路径。使用方法: trace Test t >> &
执行命令后会输出job id和cache location
7.停止命令: 异步执行的命令,如果希望停止,可执行kill

.

判断Ubuntu是否安装了ssh服务:

输入:ps -e | grep ssh 如果服务已经启动,则可以看到“sshd”,否则表示没有安装服务,或没有开机启动,如果不是下图情况,请安装ssh服务

安装ssh服务,输入命令:sudo apt-get install openssh-server

启动服务:/etc/init.d/ssh start

本机测试是否能够成功登录或其他工具链接登录即可:
ssh -l 用户名 本机ip
出现如下信息: 程序 ‘java’ 已包含在下列软件包中
尝试sudo apt install <选定的软件包>

带包编译:javac -d . 源文件

例:javac -d . TestConsole.java

带包运行:java 包名.类名 命令行参数列表

OGNL表达式
OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,他是一个开源项目。Struts框架使用OGNL作为默认的表达式语言。
Ognl取根元素不用#号,取非根元素要使用#号

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值