目录
一、Arthas学习
1、class/classloader相关命令一
1、sc
2、sm
2、class/classloader相关命令二
1、jad
2、mc
3、redefine
三、class/classloader相关命令三
Arthas(阿尔萨斯)--(一)
Arthas(阿尔萨斯)--(二)
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
。
一个程序员最重要的能力是:写出高质量的代码!!
有道无术,术尚可求也,有术无道,止于术。
无论你是年轻还是年长,所有程序员都需要记住:时刻努力学习新技术,否则就会被时代抛弃!