目录
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 | 指定 class 的 ClassLoader#toString() 返回值。长格式[classLoaderStr |
- 模糊搜索
- [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.
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
(Ljava/lang/StringBuilder;)V - java.lang.String
([CIILjava/lang/Void;)V - java.lang.String
(Ljava/lang/AbstractStringBuilder;Ljava/lang/Void;)V - java.lang.String
(Ljava/nio/charset/Charset;[BII)V - java.lang.String
([BIILjava/nio/charset/Charset;)V - java.lang.String
([BLjava/lang/String;)V - java.lang.String
([BLjava/nio/charset/Charset;)V - java.lang.String
([BII)V - java.lang.String
([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
()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.
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
, - 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
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
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
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
primeFactors(int number) { - /*44*/ if (number < 2) {
- /*45*/ ++this.illegalArgumentCount;
- throw new IllegalArgumentException("number is: " + number + ", need >= 2");
- }
- ArrayList
result = new ArrayList(); - /*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
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
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
primeFactors(int number) { - /*44*/ if (number < 2) {
- /*45*/ ++this.illegalArgumentCount;
- throw new IllegalArgumentException("number is: " + number + ", need >= 2");
- }
- ArrayList
result = new ArrayList(); - /*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
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
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
primeFactors(int number) { - /*44*/ if (number < 2) {
- /*45*/ ++this.illegalArgumentCount;
- throw new IllegalArgumentException("number is: " + number + ", need >= 2");
- }
- ArrayList
result = new ArrayList(); - /*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.
mc:Memory Compiler/内存编译器,编译.java文件生成.class。
一个程序员最重要的能力是:写出高质量的代码!!
有道无术,术尚可求也,有术无道,止于术。
无论你是年轻还是年长,所有程序员都需要记住:时刻努力学习新技术,否则就会被时代抛弃!