它主要解决的痛点:

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

看到它能解决这些问题,心里挺激动的,这不正是我们线上调试想要的吗^_^

# 支持环境

JDK 6+,Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能

# 安装

1、下载jar

默认推荐的安装方式,使用jar方式来启动

curl -O https://arthas.aliyun.com/arthas-boot.jarjava -jar arthas-boot.jar


java如何获取电脑设备码_java 获取当前ip


其实,我写本文时,用的是Windows操作系统,我直接下载的


java如何获取电脑设备码_java手机游戏下载jar_02


打印帮助信息

java -jar arthas-boot.jar -h


java如何获取电脑设备码_java为什么打不开jar_03


重点说明:--target-ip 一定要是arthas所在机器对外暴露的ip,默认是127.0.0.1,只能本地访问。

2、在线安装

此方式只适应于 Linux/Unix/Mac 等平台,命令如下:

curl -L https://arthas.aliyun.com/install.sh | sh

启动arthas

./as.sh PID #进程id 指定JAVA进程id ./as.sh -h #h来获取更多参数信

3、在docker中安装

#运行arthas-demodocker run --name arthas-demo -it hengyunabc/arthas:latest /bin/sh -c "java -jar /opt/arthas/arthas-demo.jar"#安装arthasdocker exec -it  ${containerId} /bin/bash -c "wget https://arthas.aliyun.com/arthas-boot.jar && java -jar arthas-boot.jar"

也可以很简单把Arthas安装到你的Docker镜像里,如下:

FROM openjdk:8-jdk-alpine# copy arthasCOPY --from=hengyunabc/arthas:latest /opt/arthas /opt/arthas

4、启动时,attach自身进程

1)Arthas Spring Boot Starter

目前只支持springboot 2,添加maven:

com.taobao.arthas    arthas-spring-boot-starter    ${arthas.version}

配置属性:

arthas.agent-id=hsehdfsfghhwertyfadarthas.tunnel-server=ws://47.75.156.201:7777/ws

通过访问http://localhost:8080/actuator/arthas,来查看agent-id,如下:

{    "arthasConfigMap": {        "agent-id": "hsehdfsfghhwertyfad",        "tunnel-server": "ws://47.75.156.201:7777/ws",    }}

2)非spring boot应用

添加maven依赖:

com.taobao.arthas  arthas-agent-attach  ${arthas.version}com.taobao.arthas  arthas-packaging  ${arthas.version}

添加启动代码:

import com.taobao.arthas.agent.attach.ArthasAgent;  public class ArthasAttachExample {    public static void main(String[] args) {      ArthasAgent.attach();    }}

# 远程连接

1、WebConsole

通过浏览器http访问8563端口,注意页面红色框内的IP也必须指定服务端的IP,不能用默认的127.0.0.1,如下:


java如何获取电脑设备码_java内存shell_04


2、telnet

说明一下,Windows默认telnet客服端没有开启,需要你手动开启一下。


java如何获取电脑设备码_java为什么打不开jar_05


3、tunnel server方式

下载相关jar包


java如何获取电脑设备码_java为什么打不开jar_06


启动:

java -jar  arthas-tunnel-server.jar

默认情况下,arthas tunnel server的web端口是8080,arthas agent连接的端口是7777。

启动arthas,注册到tunnel server,并指定一个agent-id:mytest123(默认是随机产生):

java -jar arthas-boot.jar --tunnel-server 'ws://192.168.1.28:7777/ws' --agent-id mytest123

如下图所示,表面生成成功:


java如何获取电脑设备码_java 获取当前ip_07


这时,便可以访问 http://localhost:8080/ ,再通过agentId连接到已注册的arthas agent上。


java如何获取电脑设备码_java手机游戏下载jar_08


最后,放一张arthas tunnel server的架构示意图,有助于我们理解tunnel server和arthas agent的关系,见下图


java如何获取电脑设备码_java为什么打不开jar_09


# 常用命令

1、Dashboard 命令

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


java如何获取电脑设备码_java手机游戏下载jar_10


2、Thread(线程监控)


java如何获取电脑设备码_java如何获取电脑设备码_11


$ thread -n 3"as-command-execute-daemon" Id=57 cpuUsage=72% RUNNABLEat 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:133)at com.taobao.arthas.core.command.monitor200.ThreadCommand.process(ThreadCommand.java:79)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:370)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)Number of locked synchronizers = 1 - java.util.concurrent.ThreadPoolExecutor$Worker@a2f70c7

可以看到这个线程是被synchroned关键字锁导致的阻塞 ,目前只支持找出synchronized关键字阻塞住的线程, 如果是java.util.concurrent.Lock, 目前还不支持。

3、trace (当前方法内部调用路径,路径上每个节点的耗时)

$ trace #类名  #方法名


java如何获取电脑设备码_java 获取当前ip_12


对于执行耗时相对较长的方法,调用链路耗时属性会高亮显示方便排查


java如何获取电脑设备码_java 获取当前ip_13


4、JVM (jvm实时运行状态,内存使用情况等)

$ jvm RUNTIME                                                                                                                                                                                                                                    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- MACHINE-NAME                                                       28679@iz2zehzeir87zi8q99krk1z                                                                                                                                            JVM-START-TIME                                                     2019-03-28 17:32:16MANAGEMENT-SPEC-VERSION                                            1.2 SPEC-NAME                                                          Java Virtual Machine Specification                                                                                                                                       SPEC-VENDOR                                                        Oracle Corporation                                                                                                                                                       SPEC-VERSION                                                       1.8 VM-NAME                                                            Java HotSpot(TM) 64-Bit Server VM                                                                                                                                        VM-VENDOR                                                          Oracle Corporation                                                                                                                                                       VM-VERSION                                                         25.191-b12                                                                                                                                                              INPUT-ARGUMENTS                                                    []                                                                                                                                                                      CLASS-PATH                                                         demo-0.0.1-SNAPSHOT.jar                                                                                                                                                  BOOT-CLASS-PATH                                                    /usr/local/jdk/jre/lib/resources.jar:/usr/local/jdk/jre/lib/rt.jar:/usr/local/jdk/jre/lib/sunrsasign.jar:/usr/local/jdk/jre/lib/jsse.jar:/usr/local/jdk/jre/lib/jce.jar                                                                     :/usr/local/jdk/jre/lib/charsets.jar:/usr/local/jdk/jre/lib/jfr.jar:/usr/local/jdk/jre/classes                                                                          LIBRARY-PATH                                                       /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib                                                                                                                                                                                                                                  -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- MACHINE-NAME                                                       28679@iz2zehzeir87zi8q99krk1z                                                                                                                                            JVM-START-TIME                                                     2019-03-28 17:32:16MANAGEMENT-SPEC-VERSION                                            1.2 SPEC-NAME                                                          Java Virtual Machine Specification                                                                                                                                       SPEC-VENDOR                                                        Oracle Corporation                                                                                                                                                       SPEC-VERSION                                                       1.8 VM-NAME                                                            Java HotSpot(TM) 64-Bit Server VM                                                                                                                                        VM-VENDOR                                                          Oracle Corporation                                                                                                                                                       VM-VERSION                                                         25.191-b12                                                                                                                                                              INPUT-ARGUMENTS                                                    []                                                                                                                                                                      CLASS-PATH                                                         demo-0.0.1-SNAPSHOT.jar                                                                                                                                                  BOOT-CLASS-PATH                                                    /usr/local/jdk/jre/lib/resources.jar:/usr/local/jdk/jre/lib/rt.jar:/usr/local/jdk/jre/lib/sunrsasign.jar:/usr/local/jdk/jre/lib/jsse.jar:/usr/local/jdk/jre/lib/jce.jar                                                                     :/usr/local/jdk/jre/lib/charsets.jar:/usr/local/jdk/jre/lib/jfr.jar:/usr/local/jdk/jre/classes                                                                          LIBRARY-PATH                                                       /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib

5、watch

当前方法执行数据观测,能观察到的范围为:返回值、抛出异常、入参

$ trace #类名  #方法名 "{params,target,returnObj,throwExp }" OGNL 表达式 {params,target,returnObj,throwExp }throwExp:异常params :入参(数组),单个参数params【0】returnObj:返回值
$ watch com.example.demo.controller index2 "{params,target,returnObj}" -x 5Press Q or Ctrl+C to abort.Affect(class-cnt:1 , method-cnt:1) cost in 81 ms.ts=2019-03-29 14:24:14; [cost=1000.746582ms] result=@ArrayList[    @Object[][        @String[辛志富],    ],    @controller[    ],    @String[index2],]

6、stack

当前方法被调用的路径,显示当前方法被那些方法调用

$ monitor -c 4 com.example.demo.controller uuidTwoPress Q or Ctrl+C to abort.Affect(class-cnt:1 , method-cnt:1) cost in 56 ms. timestamp            class                        method   total  success  fail  avg-rt(ms)  fail-rate                                                                                                                                     --------------------------------------------------------------------------------------------------------                                                                                                                                     2019-03-29 14:55:40  com.example.demo.controller  uuidTwo  7      7        0     0.18        0.00%

7、monitor 命令

监控类、方法的调用进行监控,调用次数、成功次数、失败次数、平均响应时长、失败率等。

$ classloader #每种classloader加载类的个树 name                                                    numberOfInstances  loadedCountTotal                                                                                                                                                 org.springframework.boot.loader.LaunchedURLClassLoader  1                  4463                                                                                                                                                             com.taobao.arthas.agent.ArthasClassloader               2                  3631                                                                                                                                                             BootstrapClassLoader                                    1                  2961                                                                                                                                                             java.net.FactoryURLClassLoader                          1                  835                                                                                                                                                              sun.misc.Launcher$AppClassLoader                        1                  46                                                                                                                                                               sun.reflect.DelegatingClassLoader                       41                 41                                                                                                                                                               sun.misc.Launcher$ExtClassLoader                        1                  25                                                                                                                                                              Affect(row-cnt:7) cost in 7 ms.$ classloader -t    # 类加载器间的层级关系+-BootstrapClassLoader                                                                                                                                                                                                                      +-sun.misc.Launcher$ExtClassLoader@1959f618                                                                                                                                                                                                   +-com.taobao.arthas.agent.ArthasClassloader@5fc476c6                                                                                                                                                                                        +-com.taobao.arthas.agent.ArthasClassloader@5017e14b                                                                                                                                                                                        +-sun.misc.Launcher$AppClassLoader@5c647e05                                                                                                                                                                                                   +-java.net.FactoryURLClassLoader@4ad317f0                                                                                                                                                                                                   +-org.springframework.boot.loader.LaunchedURLClassLoader@20ad9418                                                                                                                                                                       Affect(row-cnt:7) cost in 5 ms

8、classloader 命令

将JVM中所有的类加载器统计出来,树状展示

$ classloader #每种classloader加载类的个树 name                                                    numberOfInstances  loadedCountTotal                                                                                                                                                 org.springframework.boot.loader.LaunchedURLClassLoader  1                  4463                                                                                                                                                             com.taobao.arthas.agent.ArthasClassloader               2                  3631                                                                                                                                                             BootstrapClassLoader                                    1                  2961                                                                                                                                                             java.net.FactoryURLClassLoader                          1                  835                                                                                                                                                              sun.misc.Launcher$AppClassLoader                        1                  46                                                                                                                                                               sun.reflect.DelegatingClassLoader                       41                 41                                                                                                                                                               sun.misc.Launcher$ExtClassLoader                        1                  25                                                                                                                                                              Affect(row-cnt:7) cost in 7 ms.$ classloader -t    # 类加载器间的层级关系+-BootstrapClassLoader                                                                                                                                                                                                                      +-sun.misc.Launcher$ExtClassLoader@1959f618                                                                                                                                                                                                   +-com.taobao.arthas.agent.ArthasClassloader@5fc476c6                                                                                                                                                                                        +-com.taobao.arthas.agent.ArthasClassloader@5017e14b                                                                                                                                                                                        +-sun.misc.Launcher$AppClassLoader@5c647e05                                                                                                                                                                                                   +-java.net.FactoryURLClassLoader@4ad317f0                                                                                                                                                                                                   +-org.springframework.boot.loader.LaunchedURLClassLoader@20ad9418                                                                                                                                                                       Affect(row-cnt:7) cost in 5 ms

# 实战案例

我在网上看到一个动态修改上线项目的案例,我觉得比较有意思,这里整理一下给大家分享一下。

这个案例主要做了一件事情,在不停机不重启不重新发包的情况下,手动在代码中去掉抛异常代码,具体要修改的代码如下:


java如何获取电脑设备码_java内存shell_14


启动服务也达到我们预期异常


java如何获取电脑设备码_java为什么打不开jar_15


具体替换代码的流程如下:

1、jad:将需要更改的文件先进行反编译,保存下来 ,编译器修改

$ jad --source--only com.example.demo.DemoApplication > /data/DemoApplication.java

2、SC:查找当前类是哪个classLoader加载的

$ sc -d *DemoApplication | grep classLoaderclassLoaderHash   20ad9418 #类加载器  编号

3、MC:用指定的classloader重新将类在内存中编译

$ mc -c 20ad9418 /data/DemoApplication.java -d /data Memory compiler output:/data/com/example/demo/DemoApplication.class

4、redefine:将编译后的类加载到JVM,上边编译后的.class文件地址

$ redefine /data/com/example/demo/DemoApplication.class  redefine success, size: 1

文件替换后我们再次访问一下程序,发现异常没有了程序已经是我们修改正确后的,class文件替换成功


java如何获取电脑设备码_java 获取当前ip_16


结合这个案例一看,阿里出品的这款神器简直要超神了,这么多命令,记不住怎么办呢?咱们下一篇继续告诉你该怎么来玩转这些命令~