Arthas 是 Alibaba 在 2018 年 9 月开源的 Java 诊断工具。支持 JDK6+, 采用命令行交互模式,可以方便的定位和诊断线上程序运行问题。Arthas 官方文档十分详细,详见:https://alibaba.github.io/arthas

Arthas使用场景

得益于 Arthas 强大且丰富的功能,让 Arthas 能做的事情超乎想象。下面仅仅列举几项常见的使用情况,更多的使用场景可以在熟悉了 Arthas 之后自行探索。
是否有一个全局视角来查看系统的运行状况?
为什么 CPU 又升高了,到底是哪里占用了 CPU ?
运行的多线程有死锁吗?有阻塞吗?
程序运行耗时很长,是哪里耗时比较长呢?如何监测呢?
这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
有什么办法可以监控到 JVM 的实时运行状态?

一、下载arthas-boot.jar

官方提供了两种使用方式 下载arthas-boot.jar 或者直接安装使用 as. sh。 这里说明前一种。我采用下载jar包的方式

 curl -O https://alibaba.github.io/arthas/arthas-boot.jar
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  138k  100  138k    0     0   177k      0 --:--:-- --:--:-- --:--:--  176k

二、运行arthas-boot.jar

整个arthas是java语言开发的,所以可以直接java -jar运行

$ java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.5.3
[INFO] Process 67746 already using port 3658
[INFO] Process 67746 already using port 8563
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 67746 springboot-mybatis-all-1.0.0.jar
  [2]: 70997 com.huohuo.service.jvm.DeadLockTest
  [3]: 70996 org.jetbrains.jps.cmdline.Launcher
  [4]: 70570
  [5]: 70798 org.jetbrains.idea.maven.server.RemoteMavenServer36
1
[INFO] arthas home: /Users/huoyajing/.arthas/lib/3.5.5/arthas
[INFO] The target process already listen port 3658, skip attach.
[INFO] arthas-client connect 127.0.0.1 3658
  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
 /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'

wiki       https://arthas.aliyun.com/doc
tutorials  https://arthas.aliyun.com/doc/arthas-tutorials.html
version    3.5.5
main_class org.springframework.boot.loader.JarLauncher
pid        67746
time       2022-03-02 15:43:29

[arthas@67746]$

1)选择需要监控的jps进程

在这里插入图片描述
也可以直接java -jar arthas-boot.jar pid的方式直接进入主题。

注:[arthas@67746]$表明打开进入了监控客户端,在这里就可以执行相关命令进行查看了。 可以使用quit(退出当前客户端)、stop\shutdown(关闭arthas服务端,并退出所有客户端)。
67746就是PID。

2)可视化界面操作http://127.0.0.1:8563/

除了在命令行查看外,还可以通过浏览器访问http://127.0.0.1:8563/查看。如下图:可以直接操作相关的命令参数
在这里插入图片描述

三、常用命令

1)help

[arthas@73120]$ help
 NAME         DESCRIPTION
 help         Display Arthas Help
 auth         Authenticates the current session
 keymap       Display all the available keymap for the specified connection.
 sc           Search all the classes loaded by JVM
 sm           Search the method of classes loaded by JVM
 classloader  Show classloader info
 jad          Decompile class
 getstatic    Show the static field of a class
 monitor      Monitor method execution statistics, e.g. total/success/failure c
              ount, average rt, fail rate, etc.
 stack        Display the stack trace for the specified class and method
 thread       Display thread info, thread stack
 trace        Trace the execution time of specified method invocation.
 watch        Display the input/output parameter, return object, and thrown exc
              eption of specified method invocation
 tt           Time Tunnel
 jvm          Display the target JVM information
 perfcounter  Display the perf counter information.
 ognl         Execute ognl expression.
 mc           Memory compiler, compiles java files into bytecode and class file
              s in memory.
 redefine     Redefine classes. @see Instrumentation#redefineClasses(ClassDefin
              ition...)
 retransform  Retransform classes. @see Instrumentation#retransformClasses(Clas
              s...)
 dashboard    Overview of target jvm's thread, memory, gc, vm, tomcat info.
 dump         Dump class byte array from JVM
 heapdump     Heap dump
 options      View and change various Arthas options
 cls          Clear the screen
 reset        Reset all the enhanced classes
 version      Display Arthas version
 session      Display current session information
 sysprop      Display, and change the system properties.
 sysenv       Display the system env.
 vmoption     Display, and update the vm diagnostic options.
 logger       Print logger info, and update the logger level
 history      Display command history
 cat          Concatenate and print files
 base64       Encode and decode using Base64 representation
 echo         write arguments to the standard output
 pwd          Return working directory name
 mbean        Display the mbean information
 grep         grep command for pipes.
 tee          tee command for pipes.
 profiler     Async Profiler. https://github.com/jvm-profiling-tools/async-prof
              iler
 vmtool       jvm tool
 stop         Stop/Shutdown Arthas server and exit the console.

2)dashboard可以查看整个进程的运行情况,线程、内存、GC、运行环境信息

主要展示了三部分内容,线程,jvm,java-env。每过几秒会自动刷新.
在这里插入图片描述

3)thread 线程信息

其实就是dashboard获取结果的第一部分

thread -n num 查看前三个线程结果,按照CPU使用情况排序获取

[arthas@16645]$ thread -n 3
"Thread-0" Id=10 cpuUsage=99.16% deltaTime=199ms time=53423ms RUNNABLE
    at com.huohuo.service.jvm.ArthasTest.lambda$cpuHigh$1(ArthasTest.java:47)
    at com.huohuo.service.jvm.ArthasTest$$Lambda$1/1407343478.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)


"arthas-command-execute" Id=28 cpuUsage=0.16% deltaTime=0ms time=18ms RUNNABLE
    at sun.management.ThreadImpl.dumpThreads0(Native Method)
    at sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:448)
    at com.taobao.arthas.core.command.monitor200.ThreadCommand.processTopBusyThreads(ThreadCommand.java:206)
    at com.taobao.arthas.core.command.monitor200.ThreadCommand.process(ThreadCommand.java:122)
    at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:82)
    at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:18)
    at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:111)
    at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:108)
    at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:385)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:748)


"C1 CompilerThread2" [Internal] cpuUsage=0.13% deltaTime=0ms time=462ms

4)thread pid 查看某个线程具体结果

在这里插入图片描述

5)thread -b 死锁信息,不用pid

[arthas@3987]$ thread -b
"Thread-1" Id=11 BLOCKED on java.lang.Object@57d20628 owned by "Thread-2" Id=12
    at com.huohuo.service.jvm.ArthasTest.lambda$deadThread$2(ArthasTest.java:68)
    -  blocked on java.lang.Object@57d20628
    -  locked java.lang.Object@7bd50b57 <---- but blocks 1 other threads!
    at com.huohuo.service.jvm.ArthasTest$$Lambda$2/2121744517.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)
```bash
[arthas@3987]$ thread 10
"Thread-0" Id=10 RUNNABLE
    at com.huohuo.service.jvm.ArthasTest.lambda$cpuHigh$1(ArthasTest.java:44)
    at com.huohuo.service.jvm.ArthasTest$$Lambda$1/1407343478.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)

我们可以很清晰的看到问题所在 ArthasTest.java:44行有问题。

6)jad 类的全路径 反编译

这样可以方便我们查看线上代码是否是正确的版本。

[arthas@3987]$ jad com.huohuo.service.jvm.ArthasTest

//这就是类加载机制AppClassLoader(应用程序类加载器)和ExtClassLoader(扩展类加载器)
ClassLoader:
+-sun.misc.Launcher$AppClassLoader@18b4aac2
  +-sun.misc.Launcher$ExtClassLoader@7da3e221

//我的项目所在路径
Location:
/Users/huoyajing/information/spring/springBoot/J2020/springboot-mybatis-all/target/classes/

//如下是类信息,清晰明了,可以很方便查看线上是否是最新代码,太方便了

       /*
        * Decompiled with CFR.
        */
       package com.huohuo.service.jvm;

       import java.util.HashSet;

       public class ArthasTest {
           private static HashSet hashSet = new HashSet();

           public static void cpuHigh() {
               new Thread(() -> {
                   while (true) {
                       // Infinite loop
                   }
               }).start();
           }

           public static void addHashSetThread() {
               new Thread(() -> {
/*29*/             int count = 0;
                   while (true) {
                       try {
                           while (true) {
/*32*/                         hashSet.ad

......省略

7)ognl 可以查看/修改系统线上的值

ognl ‘@全路径类目@静态属性名’ 调用静态属性

[arthas@11021]$ ognl @com.huohuo.service.jvm.ArthasTest@hashSet
@HashSet[
    @String[count1],
    @String[count2],
    @String[count0],
    @String[count27],
    @String[count5],
    @String[count26],
    @String[count6],
    @String[count25],
    @String[count3],
    @String[count24],
    @String[count4],
    @String[count23],
    @String[count9],
    @String[count7],
    @String[count8],
    @String[count22],
    @String[count21],
    @String[count20],
    @String[count19],
    @String[count18],
    @String[count17],
    @String[count16],
    @String[count15],
    @String[count14],
    @String[count13],
    @String[count12],
    @String[count11],
    @String[count10],
]
[arthas@11021]$ ognl @com.huohuo.service.jvm.ArthasTest@integer
@Integer[2]

在这里插入图片描述

ognl ‘@全路径类目@静态方法名(“参数”)’ 调用静态方法

ognl ‘@com.huohuo.service.jvm.ArthasTest@hashSet.add(“huohuo”)’

8)sc -d 类全路径 类信息

[arthas@16645]$ sc -d com.huohuo.service.jvm.ArthasTest
 class-info        com.huohuo.service.jvm.ArthasTest
 code-source       /Users/huoyajing/information/spring/springBoot/J2020/springbo
                   ot-mybatis-all/target/classes/
 name              com.huohuo.service.jvm.ArthasTest
 isInterface       false
 isAnnotation      false
 isEnum            false
 isAnonymousClass  false
 isArray           false
 isLocalClass      false
 isMemberClass     false
 isPrimitive       false
 isSynthetic       false
 simple-name       ArthasTest
 modifier          public
 annotation
 interfaces
 super-class       +-java.lang.Object
 class-loader      +-sun.misc.Launcher$AppClassLoader@18b4aac2
                     +-sun.misc.Launcher$ExtClassLoader@7da3e221
 classLoaderHash   18b4aac2

Affect(row-cnt:1) cost in 33 ms.

更多命令请点击

四、 [ERROR] attach fail, targetPid: 77710

java进程是我直接idea,run启动的。

$ java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.5.1
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 70570
  [2]: 77709 org.jetbrains.jps.cmdline.Launcher
  [3]: 77710 com.huohuo.service.jvm.ArthasTest
3
[INFO] arthas home: /Users/huoyajing/.arthas/lib/3.5.5/arthas
[INFO] Try to attach process 77710
[WARN] Current VM java version: 13 do not match target VM java version: 1.8, attach may fail.
[WARN] Target VM JAVA_HOME is /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre, arthas-boot JAVA_HOME is /Library/Java/JavaVirtualMachines/jdk-13.0.2.jdk/Contents/Home, try to set the same JAVA_HOME.
[ERROR] Start arthas failed, exception stack trace:
com.sun.tools.attach.AgentLoadException: 0
	at jdk.attach/sun.tools.attach.HotSpotVirtualMachine.loadAgentLibrary(HotSpotVirtualMachine.java:108)
	at jdk.attach/sun.tools.attach.HotSpotVirtualMachine.loadAgentLibrary(HotSpotVirtualMachine.java:119)
	at jdk.attach/sun.tools.attach.HotSpotVirtualMachine.loadAgent(HotSpotVirtualMachine.java:147)
	at com.taobao.arthas.core.Arthas.attachAgent(Arthas.java:122)
	at com.taobao.arthas.core.Arthas.<init>(Arthas.java:27)
	at com.taobao.arthas.core.Arthas.main(Arthas.java:151)
[ERROR] attach fail, targetPid: 77710

在这里插入图片描述

$ java -version
java version "13.0.2" 2020-01-14
Java(TM) SE Runtime Environment (build 13.0.2+8)
Java HotSpot(TM) 64-Bit Server VM (build 13.0.2+8, mixed mode, sharing)

然后我把JDK版本切换成jdk8,确实没问题了。为何会出现这个问题呢?是因为我Idea使用的是JDK8执行的。而iTerm最开始用的是JDK13,所以版本不一样,改一下则解决了问题。

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐