Arthas-基础命令学习笔记

概述

本文主要是个人学习记录,详细教程请前往官网查看
详细教程请前往官网学习https://arthas.aliyun.com/doc/quick-start.html#

测试准备

下载demo应用并启动

# 下载
wget https://arthas.aliyun.com/math-game.jar
# 启动
java -jar math-game.jar

下载Arthas并启动

# 下载Arthas
wget https://arthas.aliyun.com/arthas-boot.jar
# 启动
java -jar arthas-boot.jar
image.png

1. 查看JVM信息

1.1 sysprop 可以打印所有的System Properties信息

[arthas@92276]$ sysprop 
 KEY                              VALUE                                                                                                                              
------------------------------------------ 
 java.vendor.url                  http://java.oracle.com/                                                                                                                                                                                                                   
 java.version                     1.8.0_211                                                                                                                          
 user.dir                         /Users/a10.11.5
......

1.2 sysprop java.version 查看指定参数

[arthas@92276]$ sysprop java.version
 KEY                              VALUE                                                                                                                              
--------------------------------------------
 java.version                     1.8.0_211     

1.3 jvm 打印jvm详细信息

[arthas@92276]$ jvm
 RUNTIME                                                                                                                                                             
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 MACHINE-NAME                                   [email protected]                                                                                            
 JVM-START-TIME                                 2022-02-07 14:13:35                                                                                                  
 MANAGEMENT-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.211-b12
...

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

[arthas@92276]$ dashboard
ID     NAME                                     GROUP                PRIORITY      STATE        %CPU          DELTA_TIME    TIME          INTERRUPTED  DAEMON        
-1     C2 CompilerThread0                       -                    -1            -            0.0           0.000         0:3.869       false        true          
-1     C2 CompilerThread2                       -                    -1            -            0.0           0.000         0:3.743       false        true          
-1     C2 CompilerThread1                       -                    -1            -            0.0           0.000         0:3.627       false        true          
33     DestroyJavaVM                            main                 5             RUNNABLE     0.0           0.000         0:3.061       false        false         
-1     C1 CompilerThread3                       -                    -1            -            0.0           0.000         0:1.788       false        true          
-1     VM Periodic Task Thread                  -                    -1            -            0.0           0.000         0:0.322       false        true          
46     arthas-NettyHttpTelnetBootstrap-3-2      system               5             RUNNABLE     0.0           0.000         0:0.138       false        true          
-1     VM Thread                                -                    -1            -            0.0           0.000         0:0.096       false        true

2. sc/sm 查看已加载的类

2.1 sc 命令可以查找到所有JVM已经加载到的类

如果搜索的是接口,还会搜索所有的实现类

[arthas@92276]$ sc javax.servlet.Filter
com.example.demo.arthas.AdminFilterConfig$AdminFilter
javax.servlet.Filter
org.apache.tomcat.websocket.server.WsFilter
org.springframework.boot.web.filter.OrderedCharacterEncodingFilter
org.springframework.boot.web.filter.OrderedHiddenHttpMethodFilter
org.springframework.boot.web.filter.OrderedHttpPutFormContentFilter
org.springframework.boot.web.filter.OrderedRequestContextFilter
org.springframework.web.filter.CharacterEncodingFilter
org.springframework.web.filter.GenericFilterBean
org.springframework.web.filter.HiddenHttpMethodFilter
org.springframework.web.filter.HttpPutFormContentFilter
org.springframework.web.filter.OncePerRequestFilter
org.springframework.web.filter.RequestContextFilter
org.springframework.web.servlet.resource.ResourceUrlEncodingFilter
Affect(row-cnt:14) cost in 5 ms.

通过-d参数,可以打印出类加载的具体信息

[arthas@92276]$ sc -d javax.servlet.Filter
 class-info        com.example.demo.arthas.AdminFilterConfig$AdminFilter                                                                                             
 code-source       file:/Users/a10.11.5/Documents/demo/demo-arthas-spring-boot.jar!/BOOT-INF/classes!/                                                               
 name              com.example.demo.arthas.AdminFilterConfig$AdminFilter                                                                                             
 isInterface       false                                                                                                                                             
 isAnnotation      false                                                                                                                                             
 isEnum            false                                                                                                                                             
 isAnonymousClass  false                                                                                                                                             
 isArray           false                                                                                                                                             
 isLocalClass      false                                                                                                                                             
 isMemberClass     true                                                                                                                                              
 isPrimitive       false                                                                                                                                             
 isSynthetic       false                                                                                                                                             
 simple-name       AdminFilter                                                                                                                                       
 modifier          static                                                                                                                                            
 annotation                                                                                                                                                          
 interfaces        javax.servlet.Filter                                                                                                                              
 super-class       +-java.lang.Object
...

2.2 sm 命令查找类的具体函数

arthas@92276]$ sm com.example.demo.arthas.user.UserController
com.example.demo.arthas.user.UserController ()V
com.example.demo.arthas.user.UserController findUserById(Ljava/lang/Integer;)Lcom/example/demo/arthas/user/User;
Affect(row-cnt:2) cost in 7 ms.

通过-d参数可以打印函数的具体属性

[arthas@92276]$ sm -d com.example.demo.arthas.user.UserController
 declaring-class   com.example.demo.arthas.user.UserController                                                                                                       
 constructor-name                                                                                                                                              
 modifier          public                                                                                                                                            
 annotation                                                                                                                                                          
 parameters                                                                                                                                                          
 exceptions                                                                                                                                                          
 classLoaderHash   5b2133b1                                                                                                                                          

 declaring-class  com.example.demo.arthas.user.UserController                                                                                                        
 method-name      findUserById                                                                                                                                       
 modifier         public                                                                                                                                             
 annotation       org.springframework.web.bind.annotation.GetMapping                                                                                                 
 parameters       java.lang.Integer                                                                                                                                  
 return           com.example.demo.arthas.user.User                                                                                                                  
 exceptions                                                                                                                                                          
 classLoaderHash  5b2133b1

3. jad反编译类

3.1 jad 命令来反编译代码

[arthas@92276]$ jad com.example.demo.arthas.user.UserController
ClassLoader:                                                                                                                                                         
+-org.springframework.boot.loader.LaunchedURLClassLoader@5b2133b1                                                                                                    
  +-sun.misc.Launcher$AppClassLoader@5c647e05                                                                                                                        
    +-sun.misc.Launcher$ExtClassLoader@452b3a41                                                                                                                      
Location:                                                                                                                                                            
file:/Users/a10.11.5/Documents/demo/demo-arthas-spring-boot.jar!/BOOT-INF/classes!/                                                                                  
       package com.example.demo.arthas.user;
       import com.example.demo.arthas.user.User;
       import org.slf4j.Logger;
       import org.slf4j.LoggerFactory;
       import org.springframework.web.bind.annotation.GetMapping;
       import org.springframework.web.bind.annotation.PathVariable;
       import org.springframework.web.bind.annotation.RestController;
       @RestController
       public class UserController {
           private static final Logger logger = LoggerFactory.getLogger(UserController.class);
           @GetMapping(value={"/user/{id}"})
           public User findUserById(@PathVariable Integer id) {
/*15*/         logger.info("id: {}", (Object)id);
/*17*/         if (id != null && id < 1) {
                   throw new IllegalArgumentException("id < 1");
               }
               return new User(id.intValue(), "name" + id);
           }
       }
Affect(row-cnt:1) cost in 128 ms.

3.2 通过--source-only参数可以只打印出在反编译的源代码

[arthas@92276]$ jad --source-only com.example.demo.arthas.user.UserController
       package com.example.demo.arthas.user;
       import com.example.demo.arthas.user.User;
       import org.slf4j.Logger;
       import org.slf4j.LoggerFactory;
       import org.springframework.web.bind.annotation.GetMapping;
       import org.springframework.web.bind.annotation.PathVariable;
       import org.springframework.web.bind.annotation.RestController;
       @RestController
       public class UserController {
           private static final Logger logger = LoggerFactory.getLogger(UserController.class);
           @GetMapping(value={"/user/{id}"})
           public User findUserById(@PathVariable Integer id) {
/*15*/         logger.info("id: {}", (Object)id);
/*17*/         if (id != null && id < 1) {
                   throw new IllegalArgumentException("id < 1");
               }
               return new User(id.intValue(), "name" + id);
           }
       }

4. Ognl动态执行代码

4.1 Ognl调用static函数

[arthas@92276]$ ognl '@[email protected]("hello ognl")'
null

4.2 获取类的静态字段

先获取类加载的hashcode,这样能定位到唯一的类

[arthas@92276]$ sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash
 classLoaderHash   5b2133b1
[arthas@92276]$ ognl -c 5b2133b1 @com.example.demo.arthas.user.UserController@logger
@Logger[
    serialVersionUID=@Long[5454405123156820674],
    FQCN=@String[ch.qos.logback.classic.Logger],
    name=@String[com.example.demo.arthas.user.UserController],
    level=null,
    effectiveLevelInt=@Integer[20000],
    parent=@Logger[Logger[com.example.demo.arthas.user]],
    childrenList=null,
    aai=null,
    additive=@Boolean[true],
    loggerContext=@LoggerContext[ch.qos.logback.classic.LoggerContext[default]],
]

还可以通过-x参数控制返回值的展开层数。比如

[arthas@92276]$ ognl -c 5b2133b1 @com.example.demo.arthas.user.UserController@logger -x 2
@Logger[
    serialVersionUID=@Long[5454405123156820674],
    FQCN=@String[ch.qos.logback.classic.Logger],
    name=@String[com.example.demo.arthas.user.UserController],
    level=null,
    effectiveLevelInt=@Integer[20000],
    parent=@Logger[
        serialVersionUID=@Long[5454405123156820674],
        FQCN=@String[ch.qos.logback.classic.Logger],
        name=@String[com.example.demo.arthas.user],
        level=null,
        effectiveLevelInt=@Integer[20000],
        parent=@Logger[Logger[com.example.demo.arthas]],
        childrenList=@CopyOnWriteArrayList[isEmpty=false;size=1],
        aai=null,
        additive=@Boolean[true],
        loggerContext=@LoggerContext[ch.qos.logback.classic.LoggerContext[default]],
    ],
...

4.3 执行多行表达式,赋值给临时变量,返回一个List

[arthas@92276]$ ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}'
@ArrayList[
    @String[/Library/Java/JavaVirtualMachines/1.8.0_211.jdk/Contents/Home/jre],
    @String[Java(TM) SE Runtime Environment],
]

5. watch 监听函数排查异常

5.1 watch监听函数命令

watch [类名] [方法名] [返回值表达式]

  • 第一个参数是类名,支持通配
  • 第二个参数是函数名,支持通配
  • 第三个参数是返回值表达式:loader,clazz,method,target,params,returnObj,throwExp,isBefore,isThrow,isReturn

示例: 监听方法的参数/返回结果.异常信息, -x 表示结果集展开2层

[arthas@92276]$ watch com.example.demo.arthas.user.UserController * '{params,returnObj,throwExp}' -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 2) cost in 28 ms, listenerId: 5
method=com.example.demo.arthas.user.UserController.findUserById location=AtExit
ts=2022-02-07 15:33:16; [cost=0.345356ms] result=@ArrayList[
    @Object[][
        @Integer[2],
    ],
    @User[
        id=@Integer[2],
        name=@String[name2],
    ],
    null,
]

5.2 条件表达式

watch [类名] [方法名] [返回值表达式] [条件表达式]

示例1: 监听方法第一个参数值大于10时打印信息
watch com.example.demo.arthas.user.UserController * '{params,returnObj,throwExp}' 'params[0]>10'

[arthas@92276]$ watch com.example.demo.arthas.user.UserController * '{params,returnObj,throwExp}' 'params[0]>10' -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 2) cost in 29 ms, listenerId: 7
method=com.example.demo.arthas.user.UserController.findUserById location=AtExit
ts=2022-02-07 15:49:29; [cost=0.389882ms] result=@ArrayList[
    @Object[][
        @Integer[12],
    ],
    @User[
        id=@Integer[12],
        name=@String[name12],
    ],
    null,
]

示例2: 监听方法抛出异常时打印信息
watch com.example.demo.arthas.user.UserController * '{params,returnObj,throwExp}' -e

[arthas@92276]$ watch com.example.demo.arthas.user.UserController * '{params,returnObj,throwExp}' -e -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 2) cost in 30 ms, listenerId: 8
method=com.example.demo.arthas.user.UserController.findUserById location=AtExceptionExit
ts=2022-02-07 15:53:58; [cost=0.314462ms] result=@ArrayList[
    @Object[][isEmpty=false;size=1],
    null,
    @IllegalArgumentException[java.lang.IllegalArgumentException: id < 1],
]

示例3: 按照耗时进行过滤
watch com.example.demo.arthas.user.UserController * '{params, returnObj}' '#cost>200'

6. jad/mc/redefine实现动态更新代码

6.1 jad 反编译UserController

jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java

  1. 把反编译的结果保存到/tmp/UserController.java
  2. 修改/tmp/UserController.java文件代码然后保存

6.2 sc查找加载UserController的ClassLoader

[arthas@92276]$ sc -d *UserController | grep classLoaderHash
 classLoaderHash   5b2133b1

6.3 使用mc(Memory Compiler)命令来把java文件编译成class文件

mc -c 5b2133b1 /tmp/UserController.java -d /tmp
把编译好class的文件保存在/tmp文件夹下

6.4 redefine命令重新加载新编译好的UserController.class

redefine /tmp/com/example/demo/arthas/user/UserController.class

6.5 检查重新加载的类

jad --source-only com.example.demo.arthas.user.UserController

7. thread查看线程信息

7.1 查看所有线程

[arthas@92276]$ thread
Threads Total: 46, NEW: 0, RUNNABLE: 12, BLOCKED: 0, WAITING: 14, TIMED_WAITING: 5, TERMINATED: 0, Internal threads: 15                                              
ID     NAME                                     GROUP                PRIORITY      STATE        %CPU          DELTA_TIME    TIME          INTERRUPTED  DAEMON        
47     arthas-command-execute                   system               5             RUNNABLE     0.12          0.000         0:6.418       false        true          
-1     C1 CompilerThread3                       -                    -1            -            0.07          0.000         0:3.646       false        true          
-1     VM Periodic Task Thread                  -                    -1            -            0.05          0.000         0:4.331       false        true          
2      Reference Handler                        system               10            WAITING      0.0           0.000         0:0.009       false        true          
3      Finalizer                                system               8             WAITING      0.0           0.000         0:0.041       false        true          
4      Signal Dispatcher                        system               9             RUNNABLE     0.0           0.000         0:0.000       false        true          
34     Attach Listener                          system               9             RUNNABLE     0.0           0.000         0:0.006       false        true                   

7.2 查看指定线程的栈

[arthas@92276]$ thread 47
"arthas-command-execute" Id=47 RUNNABLE
    at sun.management.ThreadImpl.dumpThreads0(Native Method)
    at sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:448)
    at com.taobao.arthas.core.command.monitor200.ThreadCommand.processThread(ThreadCommand.java:233)
    at com.taobao.arthas.core.command.monitor200.ThreadCommand.process(ThreadCommand.java:120)
    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)

7.3 查看CPU使用率前3线程的栈

[arthas@92276]$ thread -n 3
"C1 CompilerThread3" [Internal] cpuUsage=0.23% deltaTime=0ms time=3649ms

"arthas-command-execute" Id=47 cpuUsage=0.15% deltaTime=0ms time=6430ms 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)
...

"VM Periodic Task Thread" [Internal] cpuUsage=0.06% deltaTime=0ms time=4459ms

查看5秒内的CPU使用率前3线程栈

thread -n 3 -i 5000

7.4 查找线程是否有阻塞

[arthas@92276]$ thread -b
No most blocking thread found!

你可能感兴趣的:(Arthas-基础命令学习笔记)