【Arthas】【Java】arthas常用命令

  • Post author:
  • Post category:java


在这里插入图片描述



什么是 Arthas

摘录一段官方

Github

上的简介

Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。

当你遇到以下类似问题而束手无策时,Arthas 可以帮助你解决:

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

Arthas 支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。



Arthas 基于哪些工具开发而来

  • greys-anatomy: Arthas代码基于Greys二次开发而来,非常感谢Greys之前所有的工作,以及Greys原作者对Arthas提出的意见和建议!
  • termd: Arthas的命令行实现基于termd开发,是一款优秀的命令行程序开发框架,感谢termd提供了优秀的框架。
  • crash: Arthas的文本渲染功能基于crash中的文本渲染功能开发,可以从这里看到源码,感谢crash在这方面所做的优秀工作。
  • cli: Arthas的命令行界面基于vert.x提供的cli库进行开发,感谢vert.x在这方面做的优秀工作。
  • compiler: Arthas里的内存编绎器代码来源
  • Apache Commons Net: Arthas里的Telnet Client代码来源
  • JavaAgent:运行在 main方法之前的拦截器,它内定的方法名叫 premain ,也就是说先执行 premain 方法然后再执行 main 方法
  • ASM:一个通用的Java字节码操作和分析框架。它可以用于修改现有的类或直接以二进制形式动态生成类。ASM提供了一些常见的字节码转换和分析算法,可以从它们构建定制的复杂转换和代码分析工具。ASM提供了与其他Java字节码框架类似的功能,但是主要关注性能。因为它被设计和实现得尽可能小和快,所以非常适合在动态系统中使用(当然也可以以静态方式使用,例如在编译器中)



唯一可惜的是,arthas没有jmap -histo功能,此功能可以在线打印所有对象的数量和占用内存大小



启动

启动命令

java -jar arthas-boot.jar

   
   

不用arthas时一定要正常退出,命令如下:


  • quit

    :只是退出当前的连接。Attach到目标进程上的arthas还会继续运行,端口会保持开放,下次连接时执行

    java -jar arthas-boot.jar

    可以直接连接上。

  • exit

    :和

    quit

    命令一样的功能;

  • stop

    :完全退出arthas,

如果是非正常退出,会报下面的错误,提示端口占用。原因是上次连接了一个进程,未正常退出。

[ERROR] The telnet port 3658 is used by process 3804 instead of target process 15043, you will connect to an unexpected process.
[ERROR] 1. Try to restart arthas-boot, select process 3804, shutdown it first with running the 'stop' command.
[ERROR] 2. Or try to stop the existing arthas instance: java -jar arthas-client.jar 127.0.0.1 3658 -c "stop"
[ERROR] 3. Or try to use different telnet port, for example: java -jar arthas-boot.jar --telnet-port 9998 --http-port -1

   
   



注意: arthas依赖jdk的环境变量,也依赖一些jdk自带的工具,比如 jps,如果服务器上只有jre环境而没有jdk环境的话,是没有jps的,所以arthas也会报错;



arthas所有命令

启动arthas后,在命令行输入

help

,即可查看命令帮助信息、当前arthas版本支持的指令,或者查看具体指令的使用说明。所有的命令如下:



基础命令

命令 说明
cls 清空当前屏幕区域。
session 查看当前会话的信息,显示当前绑定的pid以及会话id。
reset 重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端stop时会重置所有增强过的类
version 输出当前目标 Java 进程所加载的 Arthas 版本号
history 打印历史命令,打印出你在使用arthas过程中输入了哪些命令。
keymap 输出arthas的快捷键映射表:



进阶命令

命令 说明
dashboard 查看当前系统的实时数据面板,例如:服务器thread信息、内存memory、GC回收等情况
thread 查看线程的堆栈信息
jvm 打印出jvm的信息,包括参数和变量,以及用的jvm名字、系统等等
sysprop 查看当前JVM的系统属性(System Property)
sysenv 查看当前JVM的环境属性(System Environment Variables)
vmoption 查看,更新VM诊断相关的参数
perfcounter 查看当前JVM的 Perf Counter信息
logger 查看logger信息,更新logger level(级别)
mbean 这个命令可以便捷的查看或监控 Mbean 的属性信息。
getstatic 通过getstatic命令可以方便的查看类的静态属性。使用方法为

getstatic class_name field_name

,推荐直接使用ognl命令,更加灵活。
ognl 执行ognl表达式,此命令可动态执行代码
sc 查看JVM已加载的类信息,可以查看类在哪个jar包里面
sm 查看已加载类的方法信息
dump dump 已加载类的 bytecode 到特定目录
heapdump dump java heap, 类似jmap命令的heap dump功能。
vmtool vmtool 利用JVMTI接口,实现查询内存对象,强制GC等功能。
jad 反编译指定已加载类的源码
classloader 查看classloader的继承树,urls,类加载信息
mc Memory Compiler/内存编译器,编译.java文件生成.class。
retransform 加载外部的.class文件,动态重新加载 jvm已加载的类。
redefine 加载外部的.class文件,redefine jvm已加载的类。这个方式只是修改运行时内存,class文件并没有改变,服务重启就失效了,推荐使用 retransform 命令
monitor 方法执行监控
watch 方法执行数据观测,让你能方便的观察到指定方法的调用情况。能观察到的范围为:返回值、抛出异常、入参,通过编写 OGNL 表达式进行对应变量的查看。
trace 方法内部调用路径,并输出方法路径上的每个节点上耗时,trace 命令能主动搜索 class-pattern/method-pattern 对应的方法调用路径,渲染和统计整个调用链路上的所有性能开销和追踪调用链路。
stack 输出当前方法被调用的调用路径
tt 方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
profiler profiler 命令支持生成应用热点的火焰图。本质上是通过不断的采样,然后把收集到的采样结果生成火焰图。
cat 打印文件内容,和linux里的cat命令类似。
echo 打印参数,和linux里的echo命令类似
grep 类似传统的grep命令
base64 base64编码转换,和linux里的 base64 命令类似。
tee 类似传统的tee命令, 用于读取标准输入的数据,并将其内容输出成文件。
pwd 返回当前的工作目录,和linux命令类似
auth 验证当前会话
options 系统的配置开关,可开启和关闭



命令介绍

这里主要介绍常用的arthas命令,不会每个命令都介绍一遍,有些命令是linux继承过来的,也没必要介绍。



session 查看当前会话的信息

这个命令非常简单,就只是打印进程的pid和会话id,注意是java的进程id,不是arthas的进程id;

[arthas@12771]$ session
 Name        Value                                                                                                                                  
--------------------------------------------------                                                                                                  
 JAVA_PID    12771                                                                                                                                  
 SESSION_ID  41d19baa-2064-442a-acf1-b8ac11801265 

   
   



history 打印命令历史

启动arthas后,你输入过的命令都会被记录起来,history则会打印出你的输入历史


  • history 5

    :查看最近执行的5条指令

  • history -c

    :清空输入的历史指令



quit 退出当前arthas客户端

只是退出当前 Arthas 客户端,其他 Arthas 客户端不受影响。等同于exit、logout、q三个指令。



stop 关闭 Arthas 服务端

执行stop指令后,所有 Arthas 客户端全部退出。关闭Arthas服务器之前,会重置掉所有做过的增强类。但是用redefine重加载的类内容不会被重置。



dashboard命令 查看当前系统的实时数据面板

查看当前系统的实时数据面板,例如:服务器thread(线程)信息、内存memory、GC回收等情况

在这里插入图片描述



数据列说明


  • 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线程



JVM内部线程

Java 8之后支持获取JVM内部线程CPU时间,这些线程只有名称和CPU时间,没有ID及状态等信息(显示ID为-1)。 通过内部线程可以观测到JVM活动,如GC、JIT编译等占用CPU情况,方便了解JVM整体运行状况。



设置刷新间隔和次数

另外,面板会默认会每5秒刷新一次,并且会一直刷新下去,如果想要指定刷新次数和间隔时间,可以这么写:

dashboard dashboard -i 1000 -n 2

   
   


-i

表示刷新的间隔时间,单位(毫秒),

-n

表表示查询的次数,到达指定次数后,自动退出dashboard面板;



thread 查看线程的堆栈信息

当没有参数时,默认显示第一页的线程信息:

thread


在这里插入图片描述

查看某个线程的堆栈:

thread 13

,13为线程的id

[arthas@12771]$ thread 13
"ContainerBackgroundProcessor[StandardEngine[Tomcat]]" Id=13 TIMED_WAITING
    at java.lang.Thread.sleep(Native Method)
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1368)
    at java.lang.Thread.run(Thread.java:748)

   
   

除此之外,thread还有其他的用法


  • thread -n 5

    :打印前5个最忙的线程并打印堆栈

  • thread -all

    :显示所有匹配的线程

  • thread -n 3 -i 1000

    :列出1000ms内最忙的3个线程栈

  • thread –state WAITING

    ,查看指定状态的线程,(

    TIMED_WAITI



    WAITING



    RUNNABLE

    等等)

  • thread -b

    :找出阻塞其他线程的线程,当出现死锁后,会提示你出现死锁的位置,代码如下
    static Object obj = new Object();
    public static void main(String[] args) throws InterruptedException, IOException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    synchronized (obj) {
                        System.out.println("我是第一个线程");
                        Thread.sleep(100000);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"yexindong-one").start();
    Thread<span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">new</span> <span class="token class-name">Thread</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Runnable</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token annotation punctuation">@Override</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            <span class="token keyword">synchronized</span> <span class="token punctuation">(</span>obj<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"我是第二个线程"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string">"yexindong-two"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

在这里插入图片描述



jvm 查看当前JVM信息

jvm显示jvm的数据汇总,具体内容分为以下几块


  • runtime

    : 包括jvm开始时间,启动参数,class_path等

  • class-loading

    :已加载类的数量,总共加载类数量,已卸载类的数量

  • garbage-collectors

    : 显示使用的垃圾收集器及垃圾收集次数

  • memory

    :堆内存空间使用情况

  • thread

    : 线程总数,守护线程数,死锁数量


thread线程相关信息如下

  • COUNT

    : JVM当前活跃的线程数

  • DAEMON-COUNT:

    JVM当前活跃的守护线程数

  • PEAK-COUNT

    : 从JVM启动开始曾经活着的最大线程数

  • STARTED-COUNT

    : 从JVM启动开始总共启动过的线程次数

  • DEADLOCK-COUNT

    : JVM当前死锁的线程数



vmoption 查看/更新虚拟机参数

这个命令可以看到我们的java项目在运行时设置了哪些参数,命令没有参数时会打印所有的vm参数

[arthas@12771]$ 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                     40                                   DEFAULT                              true                                
 MaxHeapFreeRatio                     70                                   DEFAULT                              true                                
 PrintConcurrentLocks                 false                                DEFAULT                              true         

 
 

除此之外,还可查看单个参数和动态设置参数功能,这里可以动态更新参数,不需要重启java进程;


  • vmoption PrintGCDetails

    查看指定的vm参数

  • vmoption PrintGCDetails true

    更新指定的vm参数



ognl 动态执行代码

调用静态方法:

ognl '@java.lang.System@out.println("hello yexindong")'

,执行后,可以看到控制台打印了

hello yexindong



在这里插入图片描述



sc 查看jvm已加载的类信息

简单用法

sc com.test.Test

,如果jvm已加载这个类,则会打印出该类的全类名,

[arthas@3568]$ sc com.test.Test
com.test.Test
Affect(row-cnt:1) cost in 4 ms.

 
 

但是这样的信息太过于简陋了, 加上

-d

参数可以打印类的详细信息,并且还可以查看你这个类在哪个jar包里面,命令如下

  sc -d com.test.Test

 
 

打印结果如下

[arthas@3568]$ sc -d *.Test
 class-info        com.test.Test                                                
 code-source       /Users/yexindong/Documents/java/java_project/Test/target/cla 
                   sses/                                                        
 name              com.test.Test                                                
 isInterface       false                                                        
 isAnnotation      false                                                        
 isEnum            false                                                        
 isAnonymousClass  false                                                        
 isArray           false                                                        
 isLocalClass      false                                                        
 isMemberClass     false                                                        
 isPrimitive       false                                                        
 isSynthetic       false                                                        
 simple-name       Test                                                         
 modifier          public                                                       
 annotation                                                                     
 interfaces                                                                     
 super-class       +-java.lang.Object                                           
 class-loader      +-sun.misc.Launcher$AppClassLoader@18b4aac2                  
                     +-sun.misc.Launcher$ExtClassLoader@3df8ac7c                
 classLoaderHash   18b4aac2                                                     

Affect

(

row-cnt:1

)

cost

in

17 ms.



除此之外,还可以使用模糊查询


  • sc -d *.Test

    :查询所有类名为Test的类

  • sc -d com.*

    :查询com包下面所有的类,会往所有的子包遍历



sm 查看已加载的类方法信息

查询某个类下所有的方法

[arthas@3568]$ sm com.test.Test
com.test.Test <init>()V
com.test.Test main([Ljava/lang/String;)V
Affect(row-cnt:2) cost in 4 ms.

 
 

通过结果可以看到,有2个方法,一个是main方法,另一个为构造方法,如果你未使用构造方法,在编译的时候会自动生成构造方法;

除此之外,还可以加上

-d

打印方法的详细信息 :

sm -d com.test.Test

[arthas@3568]$ sm -d com.test.Test
 declaring-class   com.test.Test                                                
 constructor-name  <init>                                                       
 modifier          public                                                       
 annotation                                                                     
 parameters                                                                     
 exceptions                                                                     
 classLoaderHash   18b4aac2                                                     

declaring-class com.test.Test

method-name main

modifier public,static

annotation

parameters java.lang.String

[


]



return

void

exceptions java.lang.InterruptedException

java.io.IOException

classLoaderHash 18b4aac2

Affect

(

row-cnt:2

)

cost

in

6 ms.



另外,还可以打印类中的某一个方法:

sm -d com.test.Test main

# 这里打印的是main方法信息
[arthas@3568]$ sm -d com.test.Test main
 declaring-class  com.test.Test                                                 
 method-name      main                                                          
 modifier         public,static                                                 
 annotation                                                                     
 parameters       java.lang.String[]                                            
 return           void                                                          
 exceptions       java.lang.InterruptedException                                
                  java.io.IOException                                           
 classLoaderHash  18b4aac2                                                      

Affect

(

row-cnt:1

)

cost

in

4 ms.



dump 将某个类的class字节码文件导出到指定目录

这个功能最大的好处就是可以导出某个指定的类,比如我想要导出Test.class文件到 指定目录。可以这样写

dump -d /Users/yexindong/Downloads com.test.Test

 
 

在这里插入图片描述

然后在指定的目录下就可以看到刚刚导出的class文件

在这里插入图片描述

经过反编译后的class文件是这样的

在这里插入图片描述

另外,也可以使用

-c

或者

--classLoaderClass

来导出指定hashcode 的类加载器加载的类


dump -c 3d4eac69 demo.*

或者

dump --classLoaderClass sun.misc.Launcher$AppClassLoader demo.*



heapdump 导出堆转储文件

这个命令和jdk自带的jmap类似,导出的文件是一个二进制文件,导出命令:

heapdump

,未指定参数时会导出所有的类,并且会在磁盘的某个地方自动创建一个临时目录,二进制文件就在那个地方;

[arthas@28747]$ heapdump
Dumping heap to /var/folders/yq/mz0mh34s2s58zpj3sf7c9d800000gn/T/heapdump2021-07-19-16-321079309703341992219.hprof ...
Heap dump file created

 
 

如果要只导出存活的对象,并且存储到指定的目录,可以这么写

heapdump --live /tmp/dump.hprof

 
 

  • --live

    表示只导出存活的对象

  • /tmp/dump.hprof

    表示导出到哪个目录,并制定文件名称;



jad 反编译class文件

这里的反编译用起来比较简单,只需要输入全类名即可反编译源码:

jad com.test.Test

,执行jad命令后还会打印出类加载器和class文件的所在目录

[arthas@3568]$ jad com.test.Test

ClassLoader:

±sun.misc.Launcher




A

p

p

C

l

a

s

s

L

o

a

d

e

r

@

18

b

4

a

a

c

2

<

/

s

p

a

n

>

+

s

u

n

.

m

i

s

c

.

L

a

u

n

c

h

e

r

<

s

p

a

n

c

l

a

s

s

=

t

o

k

e

n

v

a

r

i

a

b

l

e

>

AppClassLoader@18b4aac2</span> +-sun.misc.Launcher<span class=”token variable”>






A


ppCl


a


ss


L


o


a


d


er


@18


b


4


aa


c


2




<








/


s


p


an




>








+













s


u


n


.


mi


sc


.


L


a


u


n


c


h


er




<








s


p


an


c


l


a


ss




=











t


o


k


e


n


v


a


r


iab


l


e







>





ExtClassLoader@3df8ac7c

Location:

/Users/yexindong/Documents/java/java_project/Test/target/classes/

   /*
    * Decompiled with CFR.
    */
   package com.test<span class="token punctuation">;</span>
   
   <span class="token function">import</span> java.io.IOException<span class="token punctuation">;</span>
   
   public class Test <span class="token punctuation">{<!-- --></span>
   
       public static void main<span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> throws InterruptedException, IOException <span class="token punctuation">{<!-- --></span>
           System.out.println<span class="token punctuation">(</span><span class="token string">"hello would"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
       <span class="token punctuation">}</span>
   <span class="token punctuation">}</span>

Affect

(

row-cnt:3

)

cost

in

643 ms.



除此之外jad还可以反编译类中的某个方法,下面的代码只编译main方法,并且不显示行号,

lineNumber

默认的值是true,现在我们把它设为false就不显示行号了;

jad com.test.Test main --lineNumber false

 
 



mc 内存编译器,编译.java文件生成.class。

使用也非常简单,mc后面加上需要编译的java文件即可

mc /tmp/Test.java

 
 

也可以使用

--classLoaderClass

参数来指定类加载器,加上

-d

命令来指定输出目录

mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /tmp/UserController.java -d /tmp

 
 

编译生成.class文件之后,可以结合retransform命令实现热更新代码。



retransform 加载外部的.class文件

以下命令即可加载指定的class文件

retransform /tmp/Test.class

 
 



monitor 方法执行监控

执行以下命令既可以启动对方法的监控,

monitor -c 1 -n 2 com.test.Test show

 
 
  • 其中

    -c 1

    表示监控周期,每一秒监控一次,如果不指定,默认是120秒周期

  • -n 2

    表示一共监控2次,监控的方法为Test类中的

    show()

    方法,如果不指定,将会一直监控下去

监控结果如下

在这里插入图片描述

监控结果说明

监控项 说明
timestamp 时间戳
class Java类
method 方法(构造方法、普通方法)
total 调用次数
success 成功次数
fail 失败次数
rt 平均RT
fail-rate 失败率



watch 方法执行数据观测

watch命令可以让用户能方便的观察到指定方法的调用情况。能观察到的范围为:返回值、抛出异常、入参,通过编写 OGNL 表达式进行对应变量的查看。

1、以下命令用于观察方法出参和返回值,

watch com.test.Test show "{params,returnObj}" -x 2 -b -e -s -f 

 
 
  • 观察的方法为Test类下的

    show()

    方法,

  • "{params,returnObj}"

    是观察表达式,是一个ognl表达式,

  • -x 2

    是指定输出结果的属性遍历深度,默认值为1,为1时看不到参数的具体值,只能看到类型;

  • -b

    :在方法调用之前观察,用此命令可查看方法的入参

  • -e

    :在方法异常之后观察。用此命令可查看方法抛出的异常

  • -s

    :在方法返回之后观察,可查看方法的返回值

  • -f

    :在方法结束之后(正常返回和异常返回)观察,可查看方法的返回值和异常信息,默认打开

    -f

在这里插入图片描述



trace 方法调用链

trace 命令能主动搜索方法调用路径,,并输出方法路径上的每个节点上耗时,渲染和统计整个调用链路上的所有性能开销和追踪调用链路。

监听Test类下show方法的调用链:

trace com.test.Test show

[arthas@4805]$ trace com.test.Test show
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 28 ms, listenerId: 2
`---ts=2021-07-18 21:41:52;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@18b4aac2
    `---[0.884064ms] com.test.Test:show()
        `---[0.135646ms] com.test.Test:showChild() #38

 
 

通过结果可以看到,在main线程中show()方法调用了showChild()方法,前面的ms数是调用方法所花费的时间,

调用链属性说明


  • thread_name

    :线程名称

  • id

    :内部线程id

  • is_daemon

    : 是否为守护线程

  • priority

    :线程优先级

  • TCCL

    :类加载器



stack 输出当前方法被调用的调用路径

和trace命令类似,不同的是stack只输出调用路径,且stack可以通过表达式来过滤,就像下面这个命令,只过滤show方法第一个参数值大于320的方法,

-n 2

表示过滤2次

stack com.test.Test show 'params[0]>320' -n 2

 
 

执行结果

stack com.test.Test show 'params[0]>320' -n 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 17 ms, listenerId: 5
ts=2021-07-18 21:52:01;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@18b4aac2
    @com.test.Test.show()
        at com.test.Test.main(Test.java:27)







此处省略一次打印信息

Command execution

times

exceed limit: 2, so

command

will exit. You can

set

it with -n option.



tt 记录下指定方法每次调用的入参和返回信息

watch 虽然很方便和灵活,但需要提前想清楚观察表达式的拼写,这对排查问题而言要求太高,因为很多时候我们并不清楚问题出自于何方,只能靠蛛丝马迹进行猜测。

这个时候如果能记录下当时方法调用的所有入参和返回值、抛出的异常会对整个问题的思考与判断非常有帮助。

于是乎,TimeTunnel 命令就诞生了。执行方法如下

tt  -t -n 3 com.test.Test show

 
 
  • >

  • -t

    表示这个参数的表明希望记录下类 Test 的

    show()

    方法的每次执行情况。

  • -n 3

    :当你执行一个调用量不高的方法时可能你还能有足够的时间用 CTRL+C 中断 tt 命令记录的过程,但如果遇到调用量非常大的方法,瞬间就能将你的 JVM 内存撑爆。此时你可以通过 -n 参数指定你需要记录的次数,当达到记录次数时 Arthas 会主动中断tt命令的记录过程,避免人工操作无法停止的情况。

命令执行结果如下

[arthas@4805]$ tt  -t -n 3 com.test.Test show 
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 16 ms, listenerId: 8
 INDE  TIMESTAMP      COST(  IS-R  IS-E  OBJECT     CLASS                  METHOD               
 X                    ms)    ET    XP                                                           
------------------------------------------------------------------------------------------------
 1045  2021-07-18 21  0.327  true  fals  NULL       Test                   show                 
       :57:15         033          e                                                            
 1046  2021-07-18 21  0.100  true  fals  NULL       Test                   show                 
       :57:17         478          e                                                            
 1047  2021-07-18 21  0.160  true  fals  NULL       Test                   show                 
       :57:19         673          e                                                                                      

 
 


结果字段说明
表格字段 字段解释
INDEX 时间片段记录编号,每一个编号代表着一次调用,后续tt还有很多命令都是基于此编号指定记录操作,非常重要。
TIMESTAMP 方法执行的本机时间,记录了这个时间片段所发生的本机时间
COST(ms) 方法执行的耗时
IS-RET 方法是否以正常返回的形式结束
IS-EXP 方法是否以抛异常的形式结束
OBJECT 执行对象的hashCode(),注意,曾经有人误认为是对象在JVM中的内存地址,但很遗憾他不是。但他能帮助你简单的标记当前执行方法的类实体
CLASS 执行的类名
METHOD 执行的方法名



profiler 生成火焰图

启动profiler

 $ profiler start
 Started [cpu] profiling

 
 

获取已采集的sample的数量

$ profiler getSamples
23

 
 

查看profiler状态,可以查看当前profiler在采样哪种event和采样时间

$ profiler status
[cpu] profiling is running for 4 seconds

 
 

停止profiler—生成svg格式结果

$ profiler stop
profiler output file: /tmp/demo/arthas-output/20191125-135546.svg
OK

 
 

默认情况下,生成的结果保存到应用的工作目录下的arthas-output目录。可以通过 –file参数来指定输出结果路径。比如:

$ profiler stop --file /tmp/output.svg
profiler output file: /tmp/output.svg
OK

 
 

生成html格式结果

默认情况下,结果文件是svg格式,如果想生成html格式,可以用–format参数指定:

$ profiler stop --format html
profiler output file: /tmp/test/arthas-output/20191125-143329.html
OK

 
 

或者在–file参数里用文件名指名格式。比如–file /tmp/result.html 。

通过浏览器查看arthas-output下面的profiler结果

默认情况下,arthas使用3658端口,则可以打开: http://localhost:3658/arthas-output/ 查看到arthas-output目录下面的profiler结果:

在这里插入图片描述

点击可以查看具体的结果:

在这里插入图片描述



options 全局配置开关

查看所有的

options

[arthas@4805]$ options
 LEVEL  TYPE   NAME         VALUE  SUMMARY              DESCRIPTION                             
------------------------------------------------------------------------------------------------
 0      boole  unsafe       false  Option to support s  This option enables to proxy functional 
        an                         ystem-level class    ity of JVM classes. Due to serious secu 
                                                        rity risk a JVM crash is possibly be in 
                                                        troduced. Do not activate it unless you 
                                                         are able to manage.                    
 1      boole  dump         false  Option to dump the   This option enables the enhanced classe 
        an                         enhanced classes     s to be dumped to external file for fur 
                                                        ther de-compilation and analysis.       
 1      boole  batch-re-tr  true   Option to support b  This options enables to reTransform cla 
        an     ansform             atch reTransform Cl  sses with batch mode.                   
                                   ass                                                          
 2      boole  json-format  false  Option to support J  This option enables to format object ou 
        an                         SON format of objec  tput with JSON when -x option selected. 
                                   t output                                                     
 1      boole  disable-sub  false  Option to control i  This option disable to include sub clas 
        an     -class              nclude sub class wh  s when matching class.                  
                                   en class matching                                            
 1      boole  support-def  true   Option to control i  This option disable to include default  
        an     ault-method         nclude default meth  method in interface when matching class 
                                   od in interface whe  .                                       
                                   n class matching                                             
 1      boole  save-result  false  Option to print com  This option enables to save each comman 
        an                         mand's result to lo  d's result to log file, which path is $ 
                                   g file               {user.home}/logs/arthas-cache/result.lo 
                                                        g.                                      
 2      Strin  job-timeout  1d     Option to job timeo  This option setting job timeout,The uni 
        g                          ut                   t can be d, h, m, s for day, hour, minu 
                                                        te, second. 1d is one day in default    
 1      boole  print-paren  true   Option to print all  This option enables print files in pare 
        an     t-fields             fileds in parent c  nt class, default value true.           
                                   lass                                                         
 1      boole  verbose      false  Option to print ver  This option enables print verbose infor 
        an                         bose information     mation, default value false.            
[arthas@4805]$ 

 
 

结果字段说明

名称 默认值 描述
unsafe false 是否支持对系统级别的类进行增强,打开该开关可能导致把JVM搞挂,请慎重选择!
dump false 是否支持被增强了的类dump到外部文件中,如果打开开关,class文件会被dump到/${application working dir}/arthas-class-dump/目录下,具体位置详见控制台输出
batch-re-transform true 是否支持批量对匹配到的类执行retransform操作
json-format false 是否支持json化的输出
disable-sub-class false 是否禁用子类匹配,默认在匹配目标类的时候会默认匹配到其子类,如果想精确匹配,可以关闭此开关
support-default-method true 是否支持匹配到default method,默认会查找interface,匹配里面的default method。参考 #1105
save-result false 是否打开执行结果存日志功能,打开之后所有命令的运行结果都将保存到~/logs/arthas-cache/result.log中
job-timeout 1d 异步后台任务的默认超时时间,超过这个时间,任务自动停止;比如设置 1d, 2h, 3m, 25s,分别代表天、小时、分、秒
print-parent-fields true 是否打印在parent class里的filed


获取option的值
[arthas@4805]$ options json-format
 LEVEL  TYPE   NAME         VALUE  SUMMARY              DESCRIPTION                             
------------------------------------------------------------------------------------------------
 2      boole  json-format  false  Option to support J  This option enables to format object ou 
        an                         SON format of objec  tput with JSON when -x option selected. 
                                   t output                                                     

 
 


设置指定的option
[arthas@4805]$ options save-result true
 NAME         BEFORE-VALUE  AFTER-VALUE                                                         
----------------------------------------                                                        
 save-result  false         true    

 
 




arthas目前来说用的人还是非常多的,据说阿里内部的人都在使用这个工具来查找错误,目前来说大部分的公司都还在使用 jinfo、jmap、jstack、jhat等jdk自带的工具来找错,工具没有好坏,看你如何使用,只要能达到目的就可以!arthas这个工具的出现, 帮助我们查找故障又多了一种方法;