Arthas(阿尔萨斯)--(三)

目录

一、Arthas学习

1、class/classloader相关命令一

1、sc

2、sm

2、class/classloader相关命令二

1、jad

2、mc

3、redefine

3、class/classloader相关命令三

1、dump

2、classloader

3、monitor

4、watch

5、trace

6、stack

7、tt

8、heapdump


一、Arthas学习

Arthas(阿尔萨斯)--(一)

Arthas(阿尔萨斯)--(二)

1、class/classloader相关命令一

1、sc

sc:Search Class:查看JVM已加载的类信息,“Search-Class” 的简写,这个命令能搜索出所有已经加载到 JVM 中的 Class 信息,这个命令支持的参数有 [d][E][f] 和 [x:]

sc 默认开启了子类匹配功能,也就是说所有当前类的子类也会被搜索出来,想要精确的匹配,请打开options disable-sub-class true开关

参数名称参数说明
class-pattern类名表达式匹配
method-pattern方法名表达式匹配
[d]输出当前类的详细信息,包括这个类所加载的原始文件来源、类的声明、加载的 ClassLoader 等详细信息。
如果一个类被多个 ClassLoader 所加载,则会出现多次
[E]开启正则表达式匹配,默认为通配符匹配
[f]输出当前类的成员变量信息(需要配合参数-d 一起使用)
[x:]指定输出静态变量时属性的遍历深度,默认为 0,即直接使用 toString 输出
[c:]指定 class 的 ClassLoader 的 hashcode
[classLoaderClass:]指定执行表达式的 ClassLoader 的 class name
[n:]具有详细信息的匹配类的最大数量(默认为 100)
[cs <arg>]指定 class 的 ClassLoader#toString() 返回值。长格式[classLoaderStr <arg>]
模糊搜索
[arthas@768]$ sc demo.*
demo.MathGame
Affect(row-cnt:1) cost in 13 ms.

打印类的详细信息
[arthas@768]$ sc -d demo.MathGame
 class-info        demo.MathGame
 code-source       /C:/Users/Administrator/.arthas/lib/3.7.1/arthas/math-game.jar
 name              demo.MathGame
 isInterface       false
 isAnnotation      false
 isEnum            false
 isAnonymousClass  false
 isArray           false
 isLocalClass      false
 isMemberClass     false
 isPrimitive       false
 isSynthetic       false
 simple-name       MathGame
 modifier          public
 annotation
 interfaces
 super-class       +-java.lang.Object
 class-loader      +-jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
                     +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@364f989
 classLoaderHash   4aa298b7

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

打印出类的 Field 信息
[arthas@768]$ sc -d -f demo.MathGame
 class-info        demo.MathGame
 code-source       /C:/Users/Administrator/.arthas/lib/3.7.1/arthas/math-game.jar
 name              demo.MathGame
 isInterface       false
 isAnnotation      false
 isEnum            false
 isAnonymousClass  false
 isArray           false
 isLocalClass      false
 isMemberClass     false
 isPrimitive       false
 isSynthetic       false
 simple-name       MathGame
 modifier          public
 annotation
 interfaces
 super-class       +-java.lang.Object
 class-loader      +-jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
                     +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@364f989
 classLoaderHash   4aa298b7
 fields            name     random
                   type     java.util.Random
                   modifier private,static
                   value    java.util.Random@127d1896

                   name     illegalArgumentCount
                   type     int
                   modifier private


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

2、sm

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

“Search-Method” 的简写,这个命令能搜索出所有已经加载了 Class 信息的方法信息。

sm 命令只能看到由当前类所声明 (declaring) 的方法,父类则无法看到。

参数名称参数说明
class-pattern类名表达式匹配
method-pattern方法名表达式匹配
[d]展示每个方法的详细信息
[E]开启正则表达式匹配,默认为通配符匹配
[c:]指定 class 的 ClassLoader 的 hashcode
[classLoaderClass:]指定执行表达式的 ClassLoader 的 class name
[n:]具有详细信息的匹配类的最大数量(默认为 100)
显示String类加载的方法
[arthas@768]$ sm java.lang.String
java.lang.String <init>(Ljava/lang/StringBuilder;)V
java.lang.String <init>([CIILjava/lang/Void;)V
java.lang.String <init>(Ljava/lang/AbstractStringBuilder;Ljava/lang/Void;)V
java.lang.String <init>(Ljava/nio/charset/Charset;[BII)V
java.lang.String <init>([BIILjava/nio/charset/Charset;)V
java.lang.String <init>([BLjava/lang/String;)V
java.lang.String <init>([BLjava/nio/charset/Charset;)V
java.lang.String <init>([BII)V
java.lang.String <init>([B)V
....
java.lang.String valueOfCodePoint(I)Ljava/lang/String;
java.lang.String describeConstable()Ljava/util/Optional;
java.lang.String lambda$stripIndent$3(ILjava/lang/String;)Ljava/lang/String;
java.lang.String lambda$indent$2(ILjava/lang/String;)Ljava/lang/String;
java.lang.String lambda$indent$1(Ljava/lang/String;)Ljava/lang/String;
java.lang.String lambda$indent$0(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
Affect(row-cnt:167) cost in 24 ms.
[arthas@768]$ sm -d java.lang.String toString
 declaring-class  java.lang.String
 method-name      toString
 modifier         public
 annotation
 parameters
 return           java.lang.String
 exceptions
 classLoaderHash  null

Affect(row-cnt:1) cost in 7 ms.
[arthas@768]$ sm demo.MathGame
demo.MathGame <init>()V
demo.MathGame main([Ljava/lang/String;)V
demo.MathGame run()V
demo.MathGame print(ILjava/util/List;)V
demo.MathGame primeFactors(I)Ljava/util/List;
Affect(row-cnt:5) cost in 5 ms.

2、class/classloader相关命令二

1、jad

jad:反编译指定已加载类的源码

jad 命令将 JVM 中实际运行的 class 的 byte code 反编译成 java 代码,便于你理解业务逻辑;如需批量下载指定包的目录的 class 字节码

$ jad java.lang.String

ClassLoader:

Location:

        /*
         * Decompiled with CFR.
         */
        package java.lang;

        import java.io.ObjectStreamField;
        import java.io.Serializable;
...
        public final class String
        implements Serializable,
        Comparable<String>,
        CharSequence {
            private final char[] value;
            private int hash;
            private static final long serialVersionUID = -6849794470754667710L;
            private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];
            public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();
...
            public String(byte[] byArray, int n, int n2, Charset charset) {
/*460*/         if (charset == null) {
                    throw new NullPointerException("charset");
                }
/*462*/         String.checkBounds(byArray, n, n2);
/*463*/         this.value = StringCoding.decode(charset, byArray, n, n2);
            }
...
反编译只显示源码
[arthas@768]$ jad --source-only demo.MathGame
       /*
        * Decompiled with CFR.
        */
       package demo;

       import java.util.ArrayList;
       import java.util.List;
       import java.util.Random;
       import java.util.concurrent.TimeUnit;

       public class MathGame {
           private static Random random = new Random();
           private int illegalArgumentCount = 0;

           public static void main(String[] args) throws InterruptedException {
               MathGame game = new MathGame();
               while (true) {
/*16*/             game.run();
/*17*/             TimeUnit.SECONDS.sleep(1L);
               }
           }

           public void run() throws InterruptedException {
               try {
/*23*/             int number = random.nextInt() / 10000;
/*24*/             List<Integer> primeFactors = this.primeFactors(number);
/*25*/             MathGame.print(number, primeFactors);
               }
               catch (Exception e) {
/*28*/             System.out.println(String.format("illegalArgumentCount:%3d, ", this.illegalArgumentCount) + e.getMessage());
               }
           }

           public static void print(int number, List<Integer> primeFactors) {
               StringBuffer sb = new StringBuffer(number + "=");
/*34*/         for (int factor : primeFactors) {
/*35*/             sb.append(factor).append('*');
               }
/*37*/         if (sb.charAt(sb.length() - 1) == '*') {
/*38*/             sb.deleteCharAt(sb.length() - 1);
               }
/*40*/         System.out.println(sb);
           }

           public List<Integer> primeFactors(int number) {
/*44*/         if (number < 2) {
/*45*/             ++this.illegalArgumentCount;
                   throw new IllegalArgumentException("number is: " + number + ", need >= 2");
               }
               ArrayList<Integer> result = new ArrayList<Integer>();
/*50*/         int i = 2;
/*51*/         while (i <= number) {
/*52*/             if (number % i == 0) {
/*53*/                 result.add(i);
/*54*/                 number /= i;
/*55*/                 i = 2;
                       continue;
                   }
/*57*/             ++i;
               }
/*61*/         return result;
           }
       }

反编译指定函数

[arthas@768]$ jad demo.MathGame main

ClassLoader:
+-jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
  +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@364f989

Location:
/C:/Users/Administrator/.arthas/lib/3.7.1/arthas/math-game.jar

       public static void main(String[] args) throws InterruptedException {
           MathGame game = new MathGame();
           while (true) {
/*16*/         game.run();
/*17*/         TimeUnit.SECONDS.sleep(1L);
           }
       }

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

反编译时不显示行号

--lineNumber 参数默认值为 true,显示指定为 false 则不打印行号。

[arthas@768]$ jad demo.MathGame main --lineNumber false

ClassLoader:
+-jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
  +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@364f989

Location:
/C:/Users/Administrator/.arthas/lib/3.7.1/arthas/math-game.jar

public static void main(String[] args) throws InterruptedException {
    MathGame game = new MathGame();
    while (true) {
        game.run();
        TimeUnit.SECONDS.sleep(1L);
    }
}

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

反编译时指定 ClassLoader

[arthas@768]$ jad demo.MathGame

ClassLoader:
+-jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
  +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@364f989

Location:
/C:/Users/Administrator/.arthas/lib/3.7.1/arthas/math-game.jar

       /*
        * Decompiled with CFR.
        */
       package demo;

       import java.util.ArrayList;
       import java.util.List;
       import java.util.Random;
       import java.util.concurrent.TimeUnit;

       public class MathGame {
           private static Random random = new Random();
           private int illegalArgumentCount = 0;

           public static void main(String[] args) throws InterruptedException {
               MathGame game = new MathGame();
               while (true) {
/*16*/             game.run();
/*17*/             TimeUnit.SECONDS.sleep(1L);
               }
           }

           public void run() throws InterruptedException {
               try {
/*23*/             int number = random.nextInt() / 10000;
/*24*/             List<Integer> primeFactors = this.primeFactors(number);
/*25*/             MathGame.print(number, primeFactors);
               }
               catch (Exception e) {
/*28*/             System.out.println(String.format("illegalArgumentCount:%3d, ", this.illegalArgumentCount) + e.getMessage());
               }
           }

           public static void print(int number, List<Integer> primeFactors) {
               StringBuffer sb = new StringBuffer(number + "=");
/*34*/         for (int factor : primeFactors) {
/*35*/             sb.append(factor).append('*');
               }
/*37*/         if (sb.charAt(sb.length() - 1) == '*') {
/*38*/             sb.deleteCharAt(sb.length() - 1);
               }
/*40*/         System.out.println(sb);
           }

           public List<Integer> primeFactors(int number) {
/*44*/         if (number < 2) {
/*45*/             ++this.illegalArgumentCount;
                   throw new IllegalArgumentException("number is: " + number + ", need >= 2");
               }
               ArrayList<Integer> result = new ArrayList<Integer>();
/*50*/         int i = 2;
/*51*/         while (i <= number) {
/*52*/             if (number % i == 0) {
/*53*/                 result.add(i);
/*54*/                 number /= i;
/*55*/                 i = 2;
                       continue;
                   }
/*57*/             ++i;
               }
/*61*/         return result;
           }
       }

Affect(row-cnt:1) cost in 98 ms.
[arthas@768]$ jad demo.MathGame -c 4aa298b7

ClassLoader:
+-jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
  +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@364f989

Location:
/C:/Users/Administrator/.arthas/lib/3.7.1/arthas/math-game.jar

       /*
        * Decompiled with CFR.
        */
       package demo;

       import java.util.ArrayList;
       import java.util.List;
       import java.util.Random;
       import java.util.concurrent.TimeUnit;

       public class MathGame {
           private static Random random = new Random();
           private int illegalArgumentCount = 0;

           public static void main(String[] args) throws InterruptedException {
               MathGame game = new MathGame();
               while (true) {
/*16*/             game.run();
/*17*/             TimeUnit.SECONDS.sleep(1L);
               }
           }

           public void run() throws InterruptedException {
               try {
/*23*/             int number = random.nextInt() / 10000;
/*24*/             List<Integer> primeFactors = this.primeFactors(number);
/*25*/             MathGame.print(number, primeFactors);
               }
               catch (Exception e) {
/*28*/             System.out.println(String.format("illegalArgumentCount:%3d, ", this.illegalArgumentCount) + e.getMessage());
               }
           }

           public static void print(int number, List<Integer> primeFactors) {
               StringBuffer sb = new StringBuffer(number + "=");
/*34*/         for (int factor : primeFactors) {
/*35*/             sb.append(factor).append('*');
               }
/*37*/         if (sb.charAt(sb.length() - 1) == '*') {
/*38*/             sb.deleteCharAt(sb.length() - 1);
               }
/*40*/         System.out.println(sb);
           }

           public List<Integer> primeFactors(int number) {
/*44*/         if (number < 2) {
/*45*/             ++this.illegalArgumentCount;
                   throw new IllegalArgumentException("number is: " + number + ", need >= 2");
               }
               ArrayList<Integer> result = new ArrayList<Integer>();
/*50*/         int i = 2;
/*51*/         while (i <= number) {
/*52*/             if (number % i == 0) {
/*53*/                 result.add(i);
/*54*/                 number /= i;
/*55*/                 i = 2;
                       continue;
                   }
/*57*/             ++i;
               }
/*61*/         return result;
           }
       }

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

2、mc

mc:Memory Compiler/内存编译器,编译.java文件生成.class

准备Hello.java文件

[arthas@6940]$ cat ./Hello.java
public class Hello {

    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}
[arthas@6940]$ mc ./
./arthas-agent.jar  ./arthas-boot.jar   ./arthas-client.jar ./arthas-core.jar   ./arthas-output/
./arthas-spy.jar    ./arthas.properties ./as-service.bat    ./as.bat            ./as.sh
./async-profiler/   ./Hello.java        ./install-local.sh  ./lib/              ./logback.xml
./math-game.jar
[arthas@6940]$ mc ./Hello.java
Memory compiler output:
C:\Users\Administrator\.arthas\lib\3.7.1\arthas\Hello.class
Affect(row-cnt:1) cost in 603 ms.
// 可以通过-d命名指定输出目录
[arthas@6940]$ mc -d D:/ ./Hello.java
Memory compiler output:
D:\Hello.class
Affect(row-cnt:1) cost in 62 ms.
[arthas@6940]$

结合redefine 命令使用

3、redefine

redefine:加载外部的.class文件,redefine jvm 已加载的类。

reset命令对redefine的类无效。如果想重置,需要redefine原始的字节码。

redefine命令和jad/watch/trace/monitor/tt等命令会冲突。执行完redefine之后,如果再执行上面提到的命令,则会把redefine的字节码重置。 原因是 jdk 本身 redefine 和 Retransform 是不同的机制,同时使用两种机制来更新字节码,只有最后修改的会生效。

redefine 的限制

  • 不允许新增加 field/method
  • 正在跑的函数,没有退出不能生效,比如下面新增加的System.out.println,只有run()函数里的会生效
public class MathGame {
    public static void main(String[] args) throws InterruptedException {
        MathGame game = new MathGame();
        while (true) {
            game.run();
            TimeUnit.SECONDS.sleep(1);
            // 这个不生效,因为代码一直跑在 while里
            System.out.println("in loop");
        }
    }

    public void run() throws InterruptedException {
        // 这个生效,因为run()函数每次都可以完整结束
        System.out.println("call run()");
        try {
            int number = random.nextInt();
            List<Integer> primeFactors = primeFactors(number);
            print(number, primeFactors);

        } catch (Exception e) {
            System.out.println(String.format("illegalArgumentCount:%3d, ", illegalArgumentCount) + e.getMessage());
        }
    }
}

演示:

结合jad/mc命令使用

//1.jad把源码拿出来
[arthas@6940]$ jad --source-only demo.MathGame > D:/MathGame.java
//2.修改源码文件,按照上面代码进行修改
//3.mc进行编译修改后的源码
[arthas@6940]$ mc D:/MathGame.java -d D:/
Memory compiler output:
D:\demo\MathGame.class
Affect(row-cnt:1) cost in 279 ms.
//4.redefine到jvm中
[arthas@6940]$ redefine D:/demo/MathGame.class
redefine success, size: 1, classes:
demo.MathGame
[arthas@6940]$

显示效果

90810=2*3*3*5*1009
178273=23*23*337
illegalArgumentCount:791, number is: -25676, need >= 2
illegalArgumentCount:792, number is: -119961, need >= 2
illegalArgumentCount:793, number is: -153679, need >= 2
illegalArgumentCount:794, number is: -21585, need >= 2
illegalArgumentCount:795, number is: -80234, need >= 2
illegalArgumentCount:796, number is: -122349, need >= 2
illegalArgumentCount:797, number is: -181247, need >= 2
illegalArgumentCount:798, number is: -54153, need >= 2
illegalArgumentCount:799, number is: -150612, need >= 2
52565=5*10513
204044=2*2*29*1759
illegalArgumentCount:800, number is: -206984, need >= 2
47335=5*9467
190174=2*95087
illegalArgumentCount:801, number is: -70073, need >= 2
illegalArgumentCount:802, number is: -103961, need >= 2
call run()
163139=23*41*173
call run()
illegalArgumentCount:803, number is: -79586, need >= 2
call run()
illegalArgumentCount:804, number is: -122371, need >= 2
call run()
illegalArgumentCount:805, number is: -126238, need >= 2
call run()
  • jad 命令反编译,然后可以用其它编译器,比如 vim 来修改源码
  • mc 命令来内存编译修改过的代码
  • 用 redefine 命令加载新的字节码

3、class/classloader相关命令三

1、dump

dump 已加载类的 bytecode 到特定目录,默认保存目录:logs/arthas/classdump/

参数名称参数说明
class-pattern类名表达式匹配
[c:]类所属 ClassLoader 的 hashcode
[classLoaderClass:]指定执行表达式的 ClassLoader 的 class name
[d:]设置类文件的目标目录
[E]开启正则表达式匹配,默认为通配符匹配

演示

先把logs/arthas/classdump/目录下文件全删除

[arthas@6940]$ dump java.lang.String
 HASHCODE  CLASSLOADER  LOCATION
 null                   C:\Users\Administrator\logs\arthas\classdump\java\lang\String.class
Affect(row-cnt:1) cost in 69 ms.
[arthas@6940]$ dump demo.*
 HASHCODE  CLASSLOADER                                                        LOCATION
 4aa298b7  +-jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7         C:\Users\Administrator\logs\arthas\class
             +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@20df8ab2  dump\jdk.internal.loader.ClassLoaders$Ap
                                                                              pClassLoader-4aa298b7\demo\MathGame.clas
                                                                              s
Affect(row-cnt:1) cost in 42 ms.
[arthas@6940]$

dump 命令将 JVM 中实际运行的 class 的 byte code dump 到指定目录,适用场景批量下载指定包目录的 class 字节码;如需反编译单一类、实时查看类信息

2、classloader

查看 classloader 的继承树,urls,类加载信息

  • classloader 命令将 JVM 中所有的 classloader 的信息统计出来,并可以展示继承树,urls 等。
  • 可以让指定的 classloader 去 getResources,打印出所有查找到的 resources 的 url。对于ResourceNotFoundException比较有用。
参数名称参数说明
[l]按类加载实例进行统计
[t]打印所有 ClassLoader 的继承树
[a]列出所有 ClassLoader 加载的类,请谨慎使用
[c:]ClassLoader 的 hashcode
[classLoaderClass:]指定执行表达式的 ClassLoader 的 class name
[c: r:]用 ClassLoader 去查找 resource
[c: load:]用 ClassLoader 去加载指定的类
//按类加载类型查看统计信息
[arthas@996]$ classloader
 name                                                  numberOfInstances  loadedCountTotal
 BootstrapClassLoader                                  1                  3487
 com.taobao.arthas.agent.ArthasClassloader             1                  1373
 jdk.internal.loader.ClassLoaders$PlatformClassLoader  1                  100
 jdk.internal.loader.ClassLoaders$AppClassLoader       1                  6
Affect(row-cnt:4) cost in 8 ms.
//按类加载实例查看统计信息
[arthas@7996]$ classloader -l
 name                                                           loadedCount  hash      parent
 BootstrapClassLoader                                           3490         null      null
 com.taobao.arthas.agent.ArthasClassloader@5e5a4581             1385         5e5a4581  jdk.internal.loader.ClassLoader
                                                                                       s$PlatformClassLoader@24049080
 jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7       6            4aa298b7  jdk.internal.loader.ClassLoader
                                                                                       s$PlatformClassLoader@24049080
 jdk.internal.loader.ClassLoaders$PlatformClassLoader@24049080  100          24049080  null
Affect(row-cnt:4) cost in 7 ms.
//查看 URLClassLoader 实际的 urls
[arthas@7996]$ classloader -c 5e5a4581
file:/C:/Users/Administrator/.arthas/lib/3.7.1/arthas/arthas-core.jar
Affect(row-cnt:2) cost in 0 ms.
//使用ClassLoader去查找类的Class文件所在的位置
[arthas@7996]$ classloader -c 5e5a4581 -r java/lang/String.class
 jrt:/java.base/java/lang/String.class

Affect(row-cnt:1) cost in 1 ms.
//使用ClassLoader去加载类5e5a4581程序加载类的hash
[arthas@7996]$ classloader -c 5e5a4581 --load java.lang.String
load class success.
 class-info        java.lang.String
 code-source
 name              java.lang.String
 isInterface       false
 isAnnotation      false
 isEnum            false
 isAnonymousClass  false
 isArray           false
 isLocalClass      false
 isMemberClass     false
 isPrimitive       false
 isSynthetic       false
 simple-name       String
 modifier          final,public
 annotation
 interfaces        java.io.Serializable,java.lang.Comparable,java.lang.CharSequence,java.lang.constant.Constable,java.
                   lang.constant.ConstantDesc
 super-class       +-java.lang.Object
 class-loader
 classLoaderHash   null

[arthas@7996]$
//查看 ClassLoader 的继承树
[arthas@7996]$ classloader -t
+-BootstrapClassLoader
+-jdk.internal.loader.ClassLoaders$PlatformClassLoader@24049080
  +-com.taobao.arthas.agent.ArthasClassloader@5e5a4581
  +-jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
Affect(row-cnt:4) cost in 5 ms.
[arthas@7996]$

3、monitor

monitor:方法执行监控

  • 对匹配 class-patternmethod-patterncondition-express的类、方法的调用进行监控。
  • monitor 命令是一个非实时返回命令.
  • 实时返回命令是输入之后立即返回,而非实时返回的命令,则是不断的等待目标 Java 进程返回信息,直到用户输入 Ctrl+C 为止。
  • 服务端是以任务的形式在后台跑任务,植入的代码随着任务的中止而不会被执行,所以任务关闭后,不会对原有性能产生太大影响,而且原则上,任何 Arthas 命令不会引起原有业务逻辑的改变。
参数名称参数说明
class-pattern类名表达式匹配
method-pattern方法名表达式匹配
condition-express条件表达式
[E]开启正则表达式匹配,默认为通配符匹配
[c:]统计周期,默认值为 120 秒
[b]方法调用之前计算 condition-express
[m <arg>]指定 Class 最大匹配数量,默认值为 50。长格式为[maxMatch <arg>]
[arthas@7996]$ monitor -c 5 demo.MathGame primeFactors
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 173 ms, listenerId: 1
 timestamp         class                       method                     total    success   fail     avg-rt(  fail-ra
                                                                                                      ms)      te
-----------------------------------------------------------------------------------------------------------------------
 2023-11-19 19:41  demo.MathGame               primeFactors               5        3         2        1.67     40.00%
 :02

 timestamp         class                       method                     total    success   fail     avg-rt(  fail-ra
                                                                                                      ms)      te
-----------------------------------------------------------------------------------------------------------------------
 2023-11-19 19:41  demo.MathGame               primeFactors               5        5         0        0.19     0.00%
 :07
监控项说明
timestamp时间戳
classJava 类
method方法(构造方法、普通方法)
total调用次数
success成功次数
fail失败次数
rt平均 RT
fail-rate失败率

4、watch

watch:函数执行数据观测

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

参数名称参数说明
class-pattern类名表达式匹配
method-pattern函数名表达式匹配
express观察表达式,默认值:{params, target, returnObj}
condition-express条件表达式
[b]函数调用之前观察
[e]函数异常之后观察
[s]函数返回之后观察
[f]函数结束之后(正常返回和异常返回)观察
[E]开启正则表达式匹配,默认为通配符匹配
[x:]指定输出结果的属性遍历深度,默认为 1,最大值是 4
[m <arg>]指定 Class 最大匹配数量,默认值为 50。长格式为[maxMatch <arg>]
  • watch 命令定义了 4 个观察事件点,即 -b 函数调用前,-e 函数异常后,-s 函数返回后,-f 函数结束后
  • 4 个观察事件点 -b-e-s 默认关闭,-f 默认打开,当指定观察点被打开后,在相应事件点会对观察表达式进行求值并输出
  • 这里要注意函数入参函数出参的区别,有可能在中间被修改导致前后不一致,除了 -b 事件点 params 代表函数入参外,其余事件都代表函数出参
  • 当使用 -b 时,由于观察事件点是在函数调用前,此时返回值或异常均不存在
  • 在 watch 命令的结果里,会打印出location信息。location有三种可能值:AtEnterAtExitAtExceptionExit。对应函数入口,函数正常 return,函数抛出异常。
//观察函数调用返回时的参数、this 对象和返回值
//观察表达式,默认值是{params, target, returnObj}
[arthas@7996]$ watch demo.MathGame primeFactors -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 35 ms, listenerId: 6
method=demo.MathGame.primeFactors location=AtExit
ts=2023-11-19 20:59:13; [cost=0.9939ms] result=@ArrayList[
    @Object[][
        @Integer[1],
    ],
    @MathGame[
        random=@Random[java.util.Random@5d22bbb7],
        illegalArgumentCount=@Integer[3012],
    ],
    @ArrayList[
        @Integer[3],
        @Integer[3],
        @Integer[19079],
    ],
]
method=demo.MathGame.primeFactors location=AtExceptionExit
ts=2023-11-19 20:59:14; [cost=0.0934ms] result=@ArrayList[
    @Object[][
        @Integer[-468],
    ],
    @MathGame[
        random=@Random[java.util.Random@5d22bbb7],
        illegalArgumentCount=@Integer[3013],
    ],
    null,
]
//观察函数调用入口的参数和返回值
[arthas@7996]$ watch demo.MathGame primeFactors "{params,returnObj}" -x 2 -b
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 35 ms, listenerId: 5
method=demo.MathGame.primeFactors location=AtEnter
ts=2023-11-19 20:57:47; [cost=0.064ms] result=@ArrayList[
    @Object[][
        @Integer[-36148],
    ],
    null,
]
method=demo.MathGame.primeFactors location=AtEnter
ts=2023-11-19 20:57:48; [cost=0.0118ms] result=@ArrayList[
    @Object[][
        @Integer[-121170],
    ],
    null,
]
//按照耗时进行过滤
[arthas@7996]$ watch demo.MathGame primeFactors '{params, returnObj}' '#cost>1' -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 36 ms, listenerId: 14
method=demo.MathGame.primeFactors location=AtExit
ts=2023-11-19 21:05:31; [cost=1.278ms] result=@ArrayList[
    @Object[][
        @Integer[1],
    ],
    @ArrayList[
        @Integer[2],
        @Integer[2],
        @Integer[31249],
    ],
]
//观察当前对象中的属性
//如果想查看函数运行前后,当前对象中的属性,可以使用target关键字,代表当前对象
[arthas@7996]$ watch demo.MathGame primeFactors 'target'
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 36 ms, listenerId: 15
method=demo.MathGame.primeFactors location=AtExit
ts=2023-11-19 21:06:29; [cost=0.1039ms] result=@MathGame[
    random=@Random[java.util.Random@5d22bbb7],
    illegalArgumentCount=@Integer[3237],
]
//然后使用target.field_name访问当前对象的某个属性
[arthas@7996]$ watch demo.MathGame primeFactors 'target.illegalArgumentCount'
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 35 ms, listenerId: 16
method=demo.MathGame.primeFactors location=AtExit
ts=2023-11-19 21:07:36; [cost=0.3043ms] result=@Integer[3275]
method=demo.MathGame.primeFactors location=AtExceptionExit
ts=2023-11-19 21:07:37; [cost=0.1276ms] result=@Integer[3276]
//同时观察函数调用前和函数返回后
[arthas@7996]$ watch demo.MathGame primeFactors "{params,target,returnObj}" -x 2 -b -s -n 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 38 ms, listenerId: 19
method=demo.MathGame.primeFactors location=AtEnter
ts=2023-11-19 21:20:48; [cost=0.0432ms] result=@ArrayList[
    @Object[][
        @Integer[-159780],
    ],
    @MathGame[
        random=@Random[java.util.Random@5d22bbb7],
        illegalArgumentCount=@Integer[3672],
    ],
    null,
]
method=demo.MathGame.primeFactors location=AtEnter
ts=2023-11-19 21:20:49; [cost=0.0145ms] result=@ArrayList[
    @Object[][
        @Integer[213280],
    ],
    @MathGame[
        random=@Random[java.util.Random@5d22bbb7],
        illegalArgumentCount=@Integer[3673],
    ],
    null,
]
//条件表达式的例子,输出第1个参数小于0的情况, -n 输出2次
[arthas@7996]$ watch demo.MathGame primeFactors '{params[0], returnObj}' 'params[0]<0' -n 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 34 ms, listenerId: 20
method=demo.MathGame.primeFactors location=AtExceptionExit
ts=2023-11-19 21:26:44; [cost=0.1281ms] result=@ArrayList[
    @Integer[-182039],
    null,
]
method=demo.MathGame.primeFactors location=AtExceptionExit
ts=2023-11-19 21:26:46; [cost=0.0497ms] result=@ArrayList[
    @Integer[-32940],
    null,
]
 OPTIONS:
 -b, --before                            Watch before invocation
 -e, --exception                         Watch after throw exception
     --exclude-class-pattern <value>     exclude class name pattern, use either '.' or '/' as separator
 -x, --expand <value>                    Expand level of object (1 by default), the max value is 4
 -f, --finish                            Watch after invocation, enable by default
 -h, --help                              this help
 -n, --limits <value>                    Threshold of execution times
     --listenerId <value>                The special listenerId
 -m, --maxMatch <value>                  The maximum of matched class.
 -E, --regex                             Enable regular expression to match (wildcard matching by default)
 -M, --sizeLimit <value>                 Upper size limit in bytes for the result (10 * 1024 * 1024 by default)
 -s, --success                           Watch after successful invocation
 -v, --verbose                           Enables print verbose information, default value false.
 <class-pattern>                         The full qualified class name you want to watch
 <method-pattern>                        The method name you want to watch
 <express>                               The content you want to watch, written by ognl. Default value is '{params, ta
                                         rget, returnObj}'
                                         Examples:
                                           params
                                           params[0]
                                           'params[0]+params[1]'
                                           '{params[0], target, returnObj}'
                                           returnObj
                                           throwExp
                                           target
                                           clazz
                                           method
 <condition-express>                     Conditional expression in ognl style, for example:
                                           TRUE  : 1==1
                                           TRUE  : true
                                           FALSE : false
                                           TRUE  : 'params.length>=0'
                                           FALSE : 1==2
                                           '#cost>100'

5、trace

trace:方法内部调用路径,并输出方法路径上的每个节点上耗时

trace 命令能主动搜索 class-patternmethod-pattern 对应的方法调用路径,渲染和统计整个调用链路上的所有性能开销和追踪调用链路。

参数名称参数说明
class-pattern类名表达式匹配
method-pattern方法名表达式匹配
condition-express条件表达式
[E]开启正则表达式匹配,默认为通配符匹配
[n:]命令执行次数
#cost方法执行耗时
[m <arg>]指定 Class 最大匹配数量,默认值为 50。长格式为[maxMatch <arg>]


[arthas@7996]$ trace demo.MathGame run
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 61 ms, listenerId: 21
`---ts=2023-11-19 21:34:13;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
    `---[0.7557ms] demo.MathGame:run()
        `---[25.67% 0.194ms ] demo.MathGame:primeFactors() #24 [throws Exception]

`---ts=2023-11-19 21:34:14;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
    `---[0.9079ms] demo.MathGame:run()
        +---[25.29% 0.2296ms ] demo.MathGame:primeFactors() #24
        `---[61.82% 0.561301ms ] demo.MathGame:print() #25

//trace 次数限制
[arthas@7996]$ trace demo.MathGame run -n 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 40 ms, listenerId: 23
`---ts=2023-11-19 21:40:19;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
    `---[6.9445ms] demo.MathGame:run()
        +---[94.64% 6.5723ms ] demo.MathGame:primeFactors() #24
        `---[3.74% 0.2598ms ] demo.MathGame:print() #25

`---ts=2023-11-19 21:40:20;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
    `---[0.8495ms] demo.MathGame:run()
        `---[12.14% 0.1031ms ] demo.MathGame:primeFactors() #24 [throws Exception]

Command execution times exceed limit: 2, so command will exit. You can set it with -n option.
//包含 jdk 的函数
//--skipJDKMethod <value> skip jdk method trace, default value true.
//默认情况下,trace 不会包含 jdk 里的函数调用,如果希望 trace jdk 里的函数,需要显式设置--skipJDKMethod false
[arthas@7996]$ trace --skipJDKMethod false demo.MathGame run -n 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 53 ms, listenerId: 24
`---ts=2023-11-19 21:41:56;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
    `---[2.3922ms] demo.MathGame:run()
        +---[0.88% 0.0211ms ] java.util.Random:nextInt() #23
        +---[84.09% 2.0115ms ] demo.MathGame:primeFactors() #24
        `---[10.67% 0.2553ms ] demo.MathGame:print() #25

`---ts=2023-11-19 21:41:57;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
    `---[1.1992ms] demo.MathGame:run()
        +---[0.54% 0.0065ms ] java.util.Random:nextInt() #23
        +---[13.32% 0.1597ms ] demo.MathGame:primeFactors() #24 [throws Exception]
        +---[0.86% 0.0103ms ] java.lang.StringBuilder:<init>() #28
        +---[4.93% 0.0591ms ] java.lang.String:format() #28
        +---[1.19% min=0.0037ms,max=0.0106ms,total=0.0143ms,count=2] java.lang.StringBuilder:append() #28
        +---[1.28% 0.0153ms ] java.lang.Exception:getMessage() #28
        +---[0.54% 0.0065ms ] java.lang.StringBuilder:toString() #28
        `---[61.47% 0.7372ms ] java.io.PrintStream:println() #28

Command execution times exceed limit: 2, so command will exit. You can set it with -n option.
//根据调用耗时过滤
[arthas@7996]$ trace demo.MathGame run '#cost > 1'
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 40 ms, listenerId: 25
`---ts=2023-11-19 21:42:36;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
    `---[1.0052ms] demo.MathGame:run()
        `---[5.45% 0.0548ms ] demo.MathGame:primeFactors() #24 [throws Exception]

6、stack

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

很多时候我们都知道一个方法被执行,但这个方法被执行的路径非常多,或者你根本就不知道这个方法是从那里被执行了,此时你需要的是 stack 命令。

参数名称参数说明
class-pattern类名表达式匹配
method-pattern方法名表达式匹配
condition-express条件表达式
[E]开启正则表达式匹配,默认为通配符匹配
[n:]执行次数限制
[m <arg>]指定 Class 最大匹配数量,默认值为 50。长格式为[maxMatch <arg>]
//获取primeFactors的调用路径,primeFactors被run调用,run被main调用
[arthas@7996]$ stack demo.MathGame primeFactors
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 38 ms, listenerId: 26
ts=2023-11-19 21:49:56;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
    @demo.MathGame.primeFactors()
        at demo.MathGame.run(MathGame.java:24)
        at demo.MathGame.main(null:16)
//据条件表达式来过滤
[arthas@7996]$ stack demo.MathGame primeFactors 'params[0]<0' -n 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 39 ms, listenerId: 27
ts=2023-11-19 21:52:28;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
    @demo.MathGame.primeFactors()
        at demo.MathGame.run(MathGame.java:24)
        at demo.MathGame.main(null:16)

ts=2023-11-19 21:52:29;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
    @demo.MathGame.primeFactors()
        at demo.MathGame.run(MathGame.java:24)
        at demo.MathGame.main(null:16)

Command execution times exceed limit: 2, so command will exit. You can set it with -n option.
//据执行时间来过滤
[arthas@7996]$ stack demo.MathGame primeFactors '#cost>1'
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 38 ms, listenerId: 28
ts=2023-11-19 21:53:18;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=jdk.internal.loader.ClassLoaders$AppClassLoader@4aa298b7
    @demo.MathGame.primeFactors()
        at demo.MathGame.run(MathGame.java:24)
        at demo.MathGame.main(null:16)

7、tt

tt:TimeTunnel:方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测

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

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

于是乎,TimeTunnel 命令就诞生了。

//记录调用,对于一个最基本的使用来说,就是记录下当前方法的每次调用环境现场。
[arthas@7996]$ tt -t demo.MathGame primeFactors
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 39 ms, listenerId: 29
 INDEX  TIMESTAMP          COST(ms)  IS-RET  IS-EXP  OBJECT        CLASS                      METHOD
-----------------------------------------------------------------------------------------------------------------------
 1000   2023-11-19 22:05:55  3.2681   true   false   0x6fdb1f78    MathGame                   primeFactors
 1001   2023-11-19 22:05:56  0.0992   false  true    0x6fdb1f78    MathGame                   primeFactors
表格字段字段解释
INDEX时间片段记录编号,每一个编号代表着一次调用,后续 tt 还有很多命令都是基于此编号指定记录操作,非常重要。
TIMESTAMP方法执行的本机时间,记录了这个时间片段所发生的本机时间
COST(ms)方法执行的耗时
IS-RET方法是否以正常返回的形式结束
IS-EXP方法是否以抛异常的形式结束
OBJECT执行对象的hashCode(),注意,曾经有人误认为是对象在 JVM 中的内存地址,但很遗憾他不是。但他能帮助你简单的标记当前执行方法的类实体
CLASS执行的类名
METHOD执行的方法名
//查看调用信息
[arthas@7996]$ tt -i 1001
 INDEX            1001
 GMT-CREATE       2023-11-19 22:05:56
 COST(ms)         0.0992
 OBJECT           0x6fdb1f78
 CLASS            demo.MathGame
 METHOD           primeFactors
 IS-RETURN        false
 IS-EXCEPTION     true
 PARAMETERS[0]    @Integer[-43203]
                                    rgumentException: number is: -43203, need >= 2
                                                    s(MathGame.java:46)
                                                             )

Affect(row-cnt:1) cost in 2 ms.
//重做一次调用
[arthas@7996]$ tt -i 1001 -p
 RE-INDEX         1001
 GMT-REPLAY       2023-11-19 22:14:02
 OBJECT           0x6fdb1f78
 CLASS            demo.MathGame
 METHOD           primeFactors
 PARAMETERS[0]    @Integer[-43203]
 IS-RETURN        false
 IS-EXCEPTION     true
                                    rgumentException: number is: -43203, need >= 2
                                                    s(MathGame.java:46)
                        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java

                                      ava.lang.reflect.Method.invoke(Method.java:580)
                        at com.taobao.arthas.core.advisor.ArthasMethod.invoke(ArthasMethod.java:155)
                        at com.taobao.arthas.core.command.monitor200.TimeTunnelCommand.processPlay(TimeTunnelCommand.java:5

                        at com.taobao.arthas.core.command.monitor200.TimeTunnelCommand.process(TimeTunnelCommand.java:286)
                        at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java

                        at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.j

                        at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCo

                        at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCo

                        at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:385

                        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
                              a.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
                        at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThre

                        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
                        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
                                                hread.run(Thread.java:1583)
Time fragment[1001] successfully replayed 1 times.

[arthas@7996]$ tt -t demo.MathGame run -n 5
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 40 ms, listenerId: 30
 INDEX  TIMESTAMP          COST(ms)  IS-RET  IS-EXP  OBJECT        CLASS                      METHOD
-----------------------------------------------------------------------------------------------------------------------
 1002   2023-11-19 22:16:01  1.4637   true   false   0x6fdb1f78    MathGame                   run  
 1003   2023-11-19 22:16:02  0.4252   true   false   0x6fdb1f78    MathGame                   run
 1004   2023-11-19 22:16:03  0.2898   true   false   0x6fdb1f78    MathGame                   run 
 1005   2023-11-19 22:16:04  0.3034   true   false   0x6fdb1f78    MathGame                   run   
 1006   2023-11-19 22:16:05  0.6361   true   false   0x6fdb1f78    MathGame                   run
Command execution times exceed limit: 5, so command will exit. You can set it with -n option.
//-w, --watch-express 观察时空隧道使用ognl 表达式
//使用表达式核心变量中所有变量作为已知条件编写表达式。
[arthas@7996]$ tt -w 'target.illegalArgumentCount'  -x 1 -i 1002
@Integer[5342]
Affect(row-cnt:1) cost in 1 ms.
//获取类的静态字段、调用类的静态方法
[arthas@7996]$ tt -w '@demo.MathGame@random.nextInt(100)'  -x 1 -i 1002
@Integer[43]
Affect(row-cnt:1) cost in 10 ms.
[arthas@7996]$
  • 解决方法重载

    tt -t *Test print params.length==1

    通过制定参数个数的形式解决不同的方法签名,如果参数个数一样,你还可以这样写

    tt -t *Test print 'params[1] instanceof Integer'

  • 解决指定参数

    tt -t *Test print params[0].mobile=="13989838402"

//检索调用记录
[arthas@7996]$ tt -l
 INDEX  TIMESTAMP          COST(ms)  IS-RET  IS-EXP  OBJECT        CLASS                      METHOD
-----------------------------------------------------------------------------------------------------------------------
 1000   2023-11-19 22:05:55  3.2681   true   false   0x6fdb1f78    MathGame                   primeFactors
 1001   2023-11-19 22:05:56  0.0992   false  true    0x6fdb1f78    MathGame                   primeFactors
 1002   2023-11-19 22:16:01  1.4637   true   false   0x6fdb1f78    MathGame                   run
 1003   2023-11-19 22:16:02  0.4252   true   false   0x6fdb1f78    MathGame                   run  
 1004   2023-11-19 22:16:03  0.2898   true   false   0x6fdb1f78    MathGame                   run
 1005   2023-11-19 22:16:04  0.3034   true   false   0x6fdb1f78    MathGame                   run
 1006   2023-11-19 22:16:05  0.6361   true   false   0x6fdb1f78    MathGame                   run
Affect(row-cnt:7) cost in 1 ms.
//我需要筛选出 primeFactors 方法的调用信息
[arthas@7996]$ tt -s 'method.name=="primeFactors"'
 INDEX  TIMESTAMP          COST(ms  IS-RE  IS-EXP  OBJECT        CLASS                      METHOD
                           )        T
-----------------------------------------------------------------------------------------------------------------------
 1000   2023-11-19 22:05:55  3.2681   true   false   0x6fdb1f78    MathGame                   primeFactors
 1001   2023-11-19 22:05:56  0.0992   false  true    0x6fdb1f78    MathGame                   primeFactors
Affect(row-cnt:2) cost in 2 ms.
[arthas@7996]$

8、heapdump

dump java heap, 类似 jmap 命令的 heap dump 功能。

[arthas@58205]$ heapdump arthas-output/dump.hprof
Dumping heap to arthas-output/dump.hprof ...
Heap dump file created

只 dump live 对象

[arthas@58205]$ heapdump --live /tmp/dump.hprof
Dumping heap to /tmp/dump.hprof ...
Heap dump file created

dump 到临时文件

[arthas@58205]$ heapdump
Dumping heap to /var/folders/my/wy7c9w9j5732xbkcyt1mb4g40000gp/T/heapdump2019-09-03-16-385121018449645518991.hprof...
Heap dump file created

结合java jhat命令使用

Arthas(阿尔萨斯)--(四)

一个程序员最重要的能力是:写出高质量的代码!!
有道无术,术尚可求也,有术无道,止于术。
无论你是年轻还是年长,所有程序员都需要记住:时刻努力学习新技术,否则就会被时代抛弃!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杀神lwz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值