Java asm读取class信息
[TOC]
1 class文件查看方式
1.1 使用jdk提供的javap命令
1.1.1 javap
javap 用法: javap
其中, 可能的选项包括: -help --help -? 输出此用法消息 -version 版本信息 -v -verbose 输出附加信息 -l 输出行号和本地变量表 -public 仅显示公共类和成员 -protected 显示受保护的/公共类和成员 -package 显示程序包/受保护的/公共类 和成员 (默认) -p -private 显示所有类和成员 -c 对代码进行反汇编 -s 输出内部类型签名 -sysinfo 显示正在处理的类的 系统信息 (路径, 大小, 日期, MD5 散列) -constants 显示最终常量 -classpath 指定查找用户类文件的位置 -cp 指定查找用户类文件的位置 -bootclasspath 覆盖引导类文件的位置 1.1.2 使用javap命令查看项目中main.jar中的BusIndex.class
javap -v -cp ./main.jar com.eventbus.gen.BusIndex
1.2 使用反编译工具Luyten
1.2.1 用luyten打开main.jar
1.2.2 选项Settings/Bytecode
1.2.3 在Structure中选中BusIndex.class
1.3 反编译结果
javap -v -cp ./main.jar com.eventbus.gen.BusIndex
Classfile jar:file:/D:/projects/Sample/ASMSample/app/libs/main.jar!/com/eventbus/gen/BusIndex.class
Last modified 2016-10-10; size 1193 bytes
MD5 checksum 4ac635858d4c2533a29accf9d634f49b
Compiled from "SourceFile"
public final class com.eventbus.gen.BusIndex extends com.a.a.c.a
minor version: 0
major version: 51
flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER
Constant pool:
#1 = String #52 // showMessage
#2 = String #53 // showMessagedd
#3 = Class #38 // com/a/a/c/a
#4 = Class #39 // com/a/a/c/d
#5 = Class #40 // com/a/a/d/a
#6 = Class #41 // com/eventbus/gen/BusIndex
#7 = Class #42 // com/eventbus/gen/a
#8 = Class #43 // com/eventbus/gen/b
#9 = Class #44 // com/eventbus/gen/c
#10 = Class #45 // com/eventbus/gen/d
#11 = Class #46 // com/sample/app/Main2Activity
#12 = Class #47 // com/sample/app/MainActivity
#13 = Class #48 // com/sample/app/MainActivity$a
#14 = Class #51 // java/lang/Object
#15 = Methodref #3.#23 // com/a/a/c/a."<init>":()V
#16 = Methodref #4.#23 // com/a/a/c/d."<init>":()V
#17 = Methodref #4.#25 // com/a/a/c/d.a:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Lcom/a/a/b/a;)V
#18 = Methodref #7.#24 // com/eventbus/gen/a."<init>":(Lcom/eventbus/gen/BusIndex;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)V
#19 = Methodref #8.#24 // com/eventbus/gen/b."<init>":(Lcom/eventbus/gen/BusIndex;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)V
#20 = Methodref #9.#24 // com/eventbus/gen/c."<init>":(Lcom/eventbus/gen/BusIndex;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)V
#21 = Methodref #10.#24 // com/eventbus/gen/d."<init>":(Lcom/eventbus/gen/BusIndex;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)V
#22 = Methodref #14.#26 // java/lang/Object.getClass:()Ljava/lang/Class;
#23 = NameAndType #32:#28 // "<init>":()V
#24 = NameAndType #32:#29 // "<init>":(Lcom/eventbus/gen/BusIndex;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)V
#25 = NameAndType #37:#31 // a:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Lcom/a/a/b/a;)V
#26 = NameAndType #50:#27 // getClass:()Ljava/lang/Class;
#27 = Utf8 ()Ljava/lang/Class;
#28 = Utf8 ()V
#29 = Utf8 (Lcom/eventbus/gen/BusIndex;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)V
#30 = Utf8 (Ljava/lang/Object;)Lcom/a/a/c/d;
#31 = Utf8 (Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Lcom/a/a/b/a;)V
#32 = Utf8 <init>
#33 = Utf8 Code
#34 = Utf8 InnerClasses
#35 = Utf8 LineNumberTable
#36 = Utf8 SourceFile
#37 = Utf8 a
#38 = Utf8 com/a/a/c/a
#39 = Utf8 com/a/a/c/d
#40 = Utf8 com/a/a/d/a
#41 = Utf8 com/eventbus/gen/BusIndex
#42 = Utf8 com/eventbus/gen/a
#43 = Utf8 com/eventbus/gen/b
#44 = Utf8 com/eventbus/gen/c
#45 = Utf8 com/eventbus/gen/d
#46 = Utf8 com/sample/app/Main2Activity
#47 = Utf8 com/sample/app/MainActivity
#48 = Utf8 com/sample/app/MainActivity$a
#49 = Utf8 generateSubscribeMethodIndex
#50 = Utf8 getClass
#51 = Utf8 java/lang/Object
#52 = Utf8 showMessage
#53 = Utf8 showMessagedd
{
public com.eventbus.gen.BusIndex();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #15 // Method com/a/a/c/a."<init>":()V
4: return
LineNumberTable:
line 15: 0
public com.a.a.c.d generateSubscribeMethodIndex(java.lang.Object);
descriptor: (Ljava/lang/Object;)Lcom/a/a/c/d;
flags: ACC_PUBLIC
Code:
stack=11, locals=7, args_size=2
0: new #4 // class com/a/a/c/d
3: dup
4: invokespecial #16 // Method com/a/a/c/d."<init>":()V
7: astore_2
8: aload_1
9: invokevirtual #22 // Method java/lang/Object.getClass:()Ljava/lang/Class;
12: astore_3
13: aconst_null
14: astore 4
16: aconst_null
17: astore 5
19: aconst_null
20: astore 6
22: aload_3
23: ldc #12 // class com/sample/app/MainActivity
25: if_acmpne 104
28: ldc #13 // class com/sample/app/MainActivity$a
30: astore 4
32: ldc #5 // class com/a/a/d/a
34: astore 5
36: ldc #1 // String showMessage
38: astore 6
40: aload_2
41: aload 6
43: aload 4
45: aload 5
47: new #7 // class com/eventbus/gen/a
50: dup
51: aload_0
52: aload_1
53: aload 6
55: aload 4
57: aload 5
59: invokespecial #18 // Method com/eventbus/gen/a."<init>":(Lcom/eventbus/gen/BusIndex;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)V
62: invokevirtual #17 // Method com/a/a/c/d.a:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Lcom/a/a/b/a;)V
65: ldc #13 // class com/sample/app/MainActivity$a
67: astore 4
69: ldc #5 // class com/a/a/d/a
71: astore 5
73: ldc #2 // String showMessagedd
75: astore 6
77: aload_2
78: aload 6
80: aload 4
82: aload 5
84: new #8 // class com/eventbus/gen/b
87: dup
88: aload_0
89: aload_1
90: aload 6
92: aload 4
94: aload 5
96: invokespecial #19 // Method com/eventbus/gen/b."<init>":(Lcom/eventbus/gen/BusIndex;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)V
99: invokevirtual #17 // Method com/a/a/c/d.a:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Lcom/a/a/b/a;)V
102: aload_2
103: areturn
104: aload_3
105: ldc #11 // class com/sample/app/Main2Activity
107: if_acmpne 186
110: ldc #13 // class com/sample/app/MainActivity$a
112: astore 4
114: ldc #5 // class com/a/a/d/a
116: astore 5
118: ldc #1 // String showMessage
120: astore 6
122: aload_2
123: aload 6
125: aload 4
127: aload 5
129: new #9 // class com/eventbus/gen/c
132: dup
133: aload_0
134: aload_1
135: aload 6
137: aload 4
139: aload 5
141: invokespecial #20 // Method com/eventbus/gen/c."<init>":(Lcom/eventbus/gen/BusIndex;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)V
144: invokevirtual #17 // Method com/a/a/c/d.a:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Lcom/a/a/b/a;)V
147: ldc #13 // class com/sample/app/MainActivity$a
149: astore 4
151: ldc #5 // class com/a/a/d/a
153: astore 5
155: ldc #2 // String showMessagedd
157: astore 6
159: aload_2
160: aload 6
162: aload 4
164: aload 5
166: new #10 // class com/eventbus/gen/d
169: dup
170: aload_0
171: aload_1
172: aload 6
174: aload 4
176: aload 5
178: invokespecial #21 // Method com/eventbus/gen/d."<init>":(Lcom/eventbus/gen/BusIndex;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)V
181: invokevirtual #17 // Method com/a/a/c/d.a:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Lcom/a/a/b/a;)V
184: aload_2
185: areturn
186: aload_2
187: areturn
LineNumberTable:
line 18: 0
line 19: 8
line 20: 13
line 21: 16
line 22: 19
line 23: 22
line 24: 28
line 25: 32
line 26: 36
line 27: 40
line 33: 65
line 34: 69
line 35: 73
line 36: 77
line 42: 102
line 44: 104
line 45: 110
line 46: 114
line 47: 118
line 48: 122
line 54: 147
line 55: 151
line 56: 155
line 57: 159
line 63: 184
line 65: 186
}
InnerClasses:
#10; //class com/eventbus/gen/d
#9; //class com/eventbus/gen/c
#8; //class com/eventbus/gen/b
#7; //class com/eventbus/gen/a
public static #37= #13 of #12; //a=class com/sample/app/MainActivity$a of class com/sample/app/MainActivity
SourceFile: "SourceFile"
2 asm中与class中的指令和类型映射
2.1 Opcodes中的指令
public interface Opcodes {
// ASM API versions
int ASM4 = 4 << 16 | 0 << 8 | 0;
int ASM5 = 5 << 16 | 0 << 8 | 0;
int ASM6 = 6 << 16 | 0 << 8 | 0;
// versions
int V1_1 = 3 << 16 | 45;
int V1_2 = 0 << 16 | 46;
int V1_3 = 0 << 16 | 47;
int V1_4 = 0 << 16 | 48;
int V1_5 = 0 << 16 | 49;
int V1_6 = 0 << 16 | 50;
int V1_7 = 0 << 16 | 51;
int V1_8 = 0 << 16 | 52;
int V1_9 = 0 << 16 | 53;
// access flags
int ACC_PUBLIC = 0x0001; // class, field, method
int ACC_PRIVATE = 0x0002; // class, field, method
int ACC_PROTECTED = 0x0004; // class, field, method
int ACC_STATIC = 0x0008; // field, method
int ACC_FINAL = 0x0010; // class, field, method, parameter
int ACC_SUPER = 0x0020; // class
int ACC_SYNCHRONIZED = 0x0020; // method
int ACC_VOLATILE = 0x0040; // field
int ACC_BRIDGE = 0x0040; // method
int ACC_VARARGS = 0x0080; // method
int ACC_TRANSIENT = 0x0080; // field
int ACC_NATIVE = 0x0100; // method
int ACC_INTERFACE = 0x0200; // class
int ACC_ABSTRACT = 0x0400; // class, method
int ACC_STRICT = 0x0800; // method
int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter
int ACC_ANNOTATION = 0x2000; // class
int ACC_ENUM = 0x4000; // class(?) field inner
int ACC_MANDATED = 0x8000; // parameter
int ACC_MODULE = 0x8000; // class
// ASM specific pseudo access flags
int ACC_DEPRECATED = 0x20000; // class, field, method
// types for NEWARRAY
int T_BOOLEAN = 4;
int T_CHAR = 5;
int T_FLOAT = 6;
int T_DOUBLE = 7;
int T_BYTE = 8;
int T_SHORT = 9;
int T_INT = 10;
int T_LONG = 11;
// tags for Handle
int H_GETFIELD = 1;
int H_GETSTATIC = 2;
int H_PUTFIELD = 3;
int H_PUTSTATIC = 4;
int H_INVOKEVIRTUAL = 5;
int H_INVOKESTATIC = 6;
int H_INVOKESPECIAL = 7;
int H_NEWINVOKESPECIAL = 8;
int H_INVOKEINTERFACE = 9;
// stack map frame types
/**
* Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}.
*/
int F_NEW = -1;
/**
* Represents a compressed frame with complete frame data.
*/
int F_FULL = 0;
/**
* Represents a compressed frame where locals are the same as the locals in
* the previous frame, except that additional 1-3 locals are defined, and
* with an empty stack.
*/
int F_APPEND = 1;
/**
* Represents a compressed frame where locals are the same as the locals in
* the previous frame, except that the last 1-3 locals are absent and with
* an empty stack.
*/
int F_CHOP = 2;
/**
* Represents a compressed frame with exactly the same locals as the
* previous frame and with an empty stack.
*/
int F_SAME = 3;
/**
* Represents a compressed frame with exactly the same locals as the
* previous frame and with a single value on the stack.
*/
int F_SAME1 = 4;
// Do not try to change the following code to use auto-boxing,
// these values are compared by reference and not by value
// The constructor of Integer was deprecated in 9
// but we are stuck with it by backward compatibility
@SuppressWarnings("deprecation") Integer TOP = new Integer(0);
@SuppressWarnings("deprecation") Integer INTEGER = new Integer(1);
@SuppressWarnings("deprecation") Integer FLOAT = new Integer(2);
@SuppressWarnings("deprecation") Integer DOUBLE = new Integer(3);
@SuppressWarnings("deprecation") Integer LONG = new Integer(4);
@SuppressWarnings("deprecation") Integer NULL = new Integer(5);
@SuppressWarnings("deprecation") Integer UNINITIALIZED_THIS = new Integer(6);
// opcodes // visit method (- = idem)
int NOP = 0; // visitInsn
int ACONST_NULL = 1; // -
int ICONST_M1 = 2; // -
int ICONST_0 = 3; // -
int ICONST_1 = 4; // -
int ICONST_2 = 5; // -
int ICONST_3 = 6; // -
int ICONST_4 = 7; // -
int ICONST_5 = 8; // -
int LCONST_0 = 9; // -
int LCONST_1 = 10; // -
int FCONST_0 = 11; // -
int FCONST_1 = 12; // -
int FCONST_2 = 13; // -
int DCONST_0 = 14; // -
int DCONST_1 = 15; // -
int BIPUSH = 16; // visitIntInsn
int SIPUSH = 17; // -
int LDC = 18; // visitLdcInsn
// int LDC_W = 19; // -
// int LDC2_W = 20; // -
int ILOAD = 21; // visitVarInsn
int LLOAD = 22; // -
int FLOAD = 23; // -
int DLOAD = 24; // -
int ALOAD = 25; // -
// int ILOAD_0 = 26; // -
// int ILOAD_1 = 27; // -
// int ILOAD_2 = 28; // -
// int ILOAD_3 = 29; // -
// int LLOAD_0 = 30; // -
// int LLOAD_1 = 31; // -
// int LLOAD_2 = 32; // -
// int LLOAD_3 = 33; // -
// int FLOAD_0 = 34; // -
// int FLOAD_1 = 35; // -
// int FLOAD_2 = 36; // -
// int FLOAD_3 = 37; // -
// int DLOAD_0 = 38; // -
// int DLOAD_1 = 39; // -
// int DLOAD_2 = 40; // -
// int DLOAD_3 = 41; // -
// int ALOAD_0 = 42; // -
// int ALOAD_1 = 43; // -
// int ALOAD_2 = 44; // -
// int ALOAD_3 = 45; // -
int IALOAD = 46; // visitInsn
int LALOAD = 47; // -
int FALOAD = 48; // -
int DALOAD = 49; // -
int AALOAD = 50; // -
int BALOAD = 51; // -
int CALOAD = 52; // -
int SALOAD = 53; // -
int ISTORE = 54; // visitVarInsn
int LSTORE = 55; // -
int FSTORE = 56; // -
int DSTORE = 57; // -
int ASTORE = 58; // -
// int ISTORE_0 = 59; // -
// int ISTORE_1 = 60; // -
// int ISTORE_2 = 61; // -
// int ISTORE_3 = 62; // -
// int LSTORE_0 = 63; // -
// int LSTORE_1 = 64; // -
// int LSTORE_2 = 65; // -
// int LSTORE_3 = 66; // -
// int FSTORE_0 = 67; // -
// int FSTORE_1 = 68; // -
// int FSTORE_2 = 69; // -
// int FSTORE_3 = 70; // -
// int DSTORE_0 = 71; // -
// int DSTORE_1 = 72; // -
// int DSTORE_2 = 73; // -
// int DSTORE_3 = 74; // -
// int ASTORE_0 = 75; // -
// int ASTORE_1 = 76; // -
// int ASTORE_2 = 77; // -
// int ASTORE_3 = 78; // -
int IASTORE = 79; // visitInsn
int LASTORE = 80; // -
int FASTORE = 81; // -
int DASTORE = 82; // -
int AASTORE = 83; // -
int BASTORE = 84; // -
int CASTORE = 85; // -
int SASTORE = 86; // -
int POP = 87; // -
int POP2 = 88; // -
int DUP = 89; // -
int DUP_X1 = 90; // -
int DUP_X2 = 91; // -
int DUP2 = 92; // -
int DUP2_X1 = 93; // -
int DUP2_X2 = 94; // -
int SWAP = 95; // -
int IADD = 96; // -
int LADD = 97; // -
int FADD = 98; // -
int DADD = 99; // -
int ISUB = 100; // -
int LSUB = 101; // -
int FSUB = 102; // -
int DSUB = 103; // -
int IMUL = 104; // -
int LMUL = 105; // -
int FMUL = 106; // -
int DMUL = 107; // -
int IDIV = 108; // -
int LDIV = 109; // -
int FDIV = 110; // -
int DDIV = 111; // -
int IREM = 112; // -
int LREM = 113; // -
int FREM = 114; // -
int DREM = 115; // -
int INEG = 116; // -
int LNEG = 117; // -
int FNEG = 118; // -
int DNEG = 119; // -
int ISHL = 120; // -
int LSHL = 121; // -
int ISHR = 122; // -
int LSHR = 123; // -
int IUSHR = 124; // -
int LUSHR = 125; // -
int IAND = 126; // -
int LAND = 127; // -
int IOR = 128; // -
int LOR = 129; // -
int IXOR = 130; // -
int LXOR = 131; // -
int IINC = 132; // visitIincInsn
int I2L = 133; // visitInsn
int I2F = 134; // -
int I2D = 135; // -
int L2I = 136; // -
int L2F = 137; // -
int L2D = 138; // -
int F2I = 139; // -
int F2L = 140; // -
int F2D = 141; // -
int D2I = 142; // -
int D2L = 143; // -
int D2F = 144; // -
int I2B = 145; // -
int I2C = 146; // -
int I2S = 147; // -
int LCMP = 148; // -
int FCMPL = 149; // -
int FCMPG = 150; // -
int DCMPL = 151; // -
int DCMPG = 152; // -
int IFEQ = 153; // visitJumpInsn
int IFNE = 154; // -
int IFLT = 155; // -
int IFGE = 156; // -
int IFGT = 157; // -
int IFLE = 158; // -
int IF_ICMPEQ = 159; // -
int IF_ICMPNE = 160; // -
int IF_ICMPLT = 161; // -
int IF_ICMPGE = 162; // -
int IF_ICMPGT = 163; // -
int IF_ICMPLE = 164; // -
int IF_ACMPEQ = 165; // -
int IF_ACMPNE = 166; // -
int GOTO = 167; // -
int JSR = 168; // -
int RET = 169; // visitVarInsn
int TABLESWITCH = 170; // visiTableSwitchInsn
int LOOKUPSWITCH = 171; // visitLookupSwitch
int IRETURN = 172; // visitInsn
int LRETURN = 173; // -
int FRETURN = 174; // -
int DRETURN = 175; // -
int ARETURN = 176; // -
int RETURN = 177; // -
int GETSTATIC = 178; // visitFieldInsn
int PUTSTATIC = 179; // -
int GETFIELD = 180; // -
int PUTFIELD = 181; // -
int INVOKEVIRTUAL = 182; // visitMethodInsn
int INVOKESPECIAL = 183; // -
int INVOKESTATIC = 184; // -
int INVOKEINTERFACE = 185; // -
int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn
int NEW = 187; // visitTypeInsn
int NEWARRAY = 188; // visitIntInsn
int ANEWARRAY = 189; // visitTypeInsn
int ARRAYLENGTH = 190; // visitInsn
int ATHROW = 191; // -
int CHECKCAST = 192; // visitTypeInsn
int INSTANCEOF = 193; // -
int MONITORENTER = 194; // visitInsn
int MONITOREXIT = 195; // -
// int WIDE = 196; // NOT VISITED
int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
int IFNULL = 198; // visitJumpInsn
int IFNONNULL = 199; // -
// int GOTO_W = 200; // -
// int JSR_W = 201; // -
}
3 asm中使用ClassReader读取.class信息
3.1 ClassReader提供四个构造方法用来加载class
public ClassReader(final byte[] b)
public ClassReader(final InputStream is)
public ClassReader(final String name)
public ClassReader(final byte[] b, final int off, final int len)
3.2 读取BusIndex.class基本信息
3.2.1 加载class
ClassReader classReader = new ClassReader(BusIndex.class.getName());
3.2.2 获取类名
classReader.getClassName()
3.2.3 获取父类名
classReader.getSuperName()
3.2.4 获取接口
classReader.getInterfaces()
3.3 打印class基本信息
System.out.println(classReader.getClassName());
System.out.println(Arrays.toString(classReader.getInterfaces()));
System.out.println(classReader.getSuperName());
3.4 控制台输出结果
com/eventbus/gen/BusIndex
[]
com/a/a/c/a
3.5 使用ClassVisitor读取BusIndex.class详细信息
3.5.1 ClassReader提供了 accept方法可以遍历class的具体信息,该方法有两个重载
public void accept(final ClassVisitor classVisitor,final Attribute[] attrs, final int flags) public void accept(final ClassVisitor classVisitor,final int flags)
3.5.2 其中参数ClassVisitor用来遍历class信息, flags用来设置遍历信息级别
3.5.3 遍历class具体信息
classReader.accept(new SimpleClassVisitor(), 0); static class SimpleClassVisitor extends ClassVisitor {
public SimpleClassVisitor() { super(Opcodes.ASM6); } @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { super.visit(version, access, name, signature, superName, interfaces); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", version:"+version+", access:"+access+", name:"+name+", signature:"+signature+", supperName:"+signature+", interfaces:"+ Arrays.toString(interfaces)); } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", desc:"+desc+", visible:"+visible); return super.visitAnnotation(desc, visible); } @Override public void visitAttribute(Attribute attr) { super.visitAttribute(attr); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", attr:"+attr); } @Override public void visitEnd() { super.visitEnd(); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()); } @Override public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", access:"+access+", name:"+name+", desc:"+desc+", signature:"+signature+", value:"+value); return super.visitField(access, name, desc, signature, value); } @Override public void visitInnerClass(String name, String outerName, String innerName, int access) { System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", name:"+name+", outerName:"+outerName+", innerName:"+innerName+", access:"+access); super.visitInnerClass(name, outerName, innerName, access); } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", access:"+access+", name:"+name+", desc:"+desc+", signature:"+signature+", exceptions:"+Arrays.toString(exceptions)); return super.visitMethod(access, name, desc, signature, exceptions); } @Override public ModuleVisitor visitModule() { System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()); return super.visitModule(); } @Override public void visitOuterClass(String owner, String name, String desc) { System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", owner:"+owner+", name:"+name+", desc:"+desc); super.visitOuterClass(owner, name, desc); } @Override public void visitSource(String source, String debug) { System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", source:"+source+", debug:"+debug); super.visitSource(source, debug); } @Override public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", typeRef:"+typeRef+", typePath:"+typePath+", desc:"+desc+", visible:"+visible); return super.visitTypeAnnotation(typeRef, typePath, desc, visible); } }
3.5.4 控制台输出结果
visit, version:51, access:49, name:com/eventbus/gen/BusIndex, signature:null, supperName:null, interfaces:[] visitSource, source:SourceFile, debug:null visitInnerClass, name:com/eventbus/gen/d, outerName:null, innerName:null, access:0 visitInnerClass, name:com/eventbus/gen/c, outerName:null, innerName:null, access:0 visitInnerClass, name:com/eventbus/gen/b, outerName:null, innerName:null, access:0 visitInnerClass, name:com/eventbus/gen/a, outerName:null, innerName:null, access:0 visitInnerClass, name:com/sample/app/MainActivity$a, outerName:com/sample/app/MainActivity, innerName:a, access:9 visitMethod, access:1, name:
, desc:()V, signature:null, exceptions:null visitMethod, access:1, name:generateSubscribeMethodIndex, desc:(Ljava/lang/Object;)Lcom/a/a/c/d;, signature:null, exceptions:null visitEnd 3.5.5 从输入结果中可以看出
- version:
version:51 与反编译结果一致
- flags:
access:49 与反编译结果一致Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL+Opcodes.ACC_SUPER = 49
- InnerClasses:
visitInnerClass, name:com/eventbus/gen/d, outerName:null, innerName:null, access:0 visitInnerClass, name:com/eventbus/gen/c, outerName:null, innerName:null, access:0 visitInnerClass, name:com/eventbus/gen/b, outerName:null, innerName:null, access:0 visitInnerClass, name:com/eventbus/gen/a, outerName:null, innerName:null, access:0 visitInnerClass, name:com/sample/app/MainActivity$a, outerName:com/sample/app/MainActivity, innerName:a, access:9
- method:
visitMethod, access:1, name:
, desc:()V, signature:null, exceptions:null visitMethod, access:1, name:generateSubscribeMethodIndex, desc:(Ljava/lang/Object;)Lcom/a/a/c/d;, signature:null, exceptions:null
3.6 使用MethodVisitor读取BusIndex.class中方法的详细信息
3.6.1 ClassVisitor的visitMethod只能获取方法的基本信息,如果要获取方法的详细信息就必须在visitMethod返回一个自定义的MethodVisitor。
static class SimpleMethodVisitor extends MethodVisitor{ public SimpleMethodVisitor(MethodVisitor mv) { super(Opcodes.ASM6, mv); } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", desc:"+desc+", visible:"+visible); return super.visitAnnotation(desc, visible); } @Override public AnnotationVisitor visitAnnotationDefault() { System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()); return super.visitAnnotationDefault(); } @Override public void visitAttribute(Attribute attr) { super.visitAttribute(attr); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", attr:"+attr); } @Override public void visitCode() { super.visitCode(); System.out.println("visitor method begin."); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()); } @Override public void visitEnd() { super.visitEnd(); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()); System.out.println("visitor method ended."); } @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { super.visitFieldInsn(opcode, owner, name, desc); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", opcode:"+Optcodes.options.get(opcode)+", owner:"+owner+", name:"+name+", desc:"+desc); } @Override public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { super.visitFrame(type, nLocal, local, nStack, stack); } @Override public void visitIincInsn(int var, int increment) { super.visitIincInsn(var, increment); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", var:"+var+", increment:"+increment); } @Override public void visitInsn(int opcode) { super.visitInsn(opcode); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", opcode:"+Optcodes.options.get(opcode)); } @Override public AnnotationVisitor visitInsnAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", typeRef:"+typeRef+", typePath:"+typePath+", desc:"+desc+", visible:"+visible); return super.visitInsnAnnotation(typeRef, typePath, desc, visible); } @Override public void visitIntInsn(int opcode, int operand) { super.visitIntInsn(opcode, operand); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", opcode:"+Optcodes.options.get(opcode)+", operand:"+operand); } @Override public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); } @Override public void visitJumpInsn(int opcode, Label label) { super.visitJumpInsn(opcode, label); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", opcode:"+Optcodes.options.get(opcode)+", label:"+label); } @Override public void visitLabel(Label label) { super.visitLabel(label); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", label:"+label); } @Override public void visitLdcInsn(Object cst) { super.visitLdcInsn(cst); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", cst:"+cst); } @Override public void visitLineNumber(int line, Label start) { super.visitLineNumber(line, start); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", line:"+line+", start label:"+line); } @Override public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { super.visitLocalVariable(name, desc, signature, start, end, index); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", name:"+name+", desc:"+desc+", signature:"+signature); } @Override public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String desc, boolean visible) { return super.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, desc, visible); } @Override public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { super.visitLookupSwitchInsn(dflt, keys, labels); } @Override public void visitMaxs(int maxStack, int maxLocals) { super.visitMaxs(maxStack, maxLocals); } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { super.visitMethodInsn(opcode, owner, name, desc, itf); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", opcode:"+Optcodes.options.get(opcode)+", owner:"+owner+", name:"+name+", desc:"+desc); } @Override public void visitMultiANewArrayInsn(String desc, int dims) { super.visitMultiANewArrayInsn(desc, dims); } @Override public void visitParameter(String name, int access) { super.visitParameter(name, access); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", name:"+name+", access:"+access); } @Override public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) { return super.visitParameterAnnotation(parameter, desc, visible); } @Override public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { super.visitTableSwitchInsn(min, max, dflt, labels); } @Override public AnnotationVisitor visitTryCatchAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { return super.visitTryCatchAnnotation(typeRef, typePath, desc, visible); } @Override public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { super.visitTryCatchBlock(start, end, handler, type); } @Override public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { return super.visitTypeAnnotation(typeRef, typePath, desc, visible); } @Override public void visitTypeInsn(int opcode, String type) { super.visitTypeInsn(opcode, type); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", opcode:"+ Optcodes.options.get(opcode)+", type:"+type); } @Override public void visitVarInsn(int opcode, int var) { super.visitVarInsn(opcode, var); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", opcode:"+ Optcodes.options.get(opcode)+",var:"+var); } }
3.6.2 在ClassVisitor的visitMethod方法中使用SimpleMethodVisitor获取generateSubscribeMethodIndex方法的具体信息
@Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions); System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName()+", access:"+access+", name:"+name+", desc:"+desc+", signature:"+signature+", exceptions:"+Arrays.toString(exceptions)); if(name.equals("generateSubscribeMethodIndex")){ return new SimpleMethodVisitor(methodVisitor); } return methodVisitor; }
3.6.3 输出结果
visit, version:51, access:49, name:com/eventbus/gen/BusIndex, signature:null, supperName:null, interfaces:[] visitSource, source:SourceFile, debug:null visitInnerClass, name:com/eventbus/gen/d, outerName:null, innerName:null, access:0 visitInnerClass, name:com/eventbus/gen/c, outerName:null, innerName:null, access:0 visitInnerClass, name:com/eventbus/gen/b, outerName:null, innerName:null, access:0 visitInnerClass, name:com/eventbus/gen/a, outerName:null, innerName:null, access:0 visitInnerClass, name:com/sample/app/MainActivity$a, outerName:com/sample/app/MainActivity, innerName:a, access:9 visitMethod, access:1, name:
, desc:()V, signature:null, exceptions:null visitMethod, access:1, name:generateSubscribeMethodIndex, desc:(Ljava/lang/Object;)Lcom/a/a/c/d;, signature:null, exceptions:null visitor method begin. visitCode visitLabel, label:L1072591677 visitLineNumber, line:18, start label:18 visitTypeInsn, opcode:NEW, type:com/a/a/c/d visitInsn, opcode:DUP visitMethodInsn, opcode:INVOKESPECIAL, owner:com/a/a/c/d, name: , desc:()V visitVarInsn, opcode:ASTORE,var:2 visitLabel, label:L918221580 visitLineNumber, line:19, start label:19 visitVarInsn, opcode:ALOAD,var:1 visitMethodInsn, opcode:INVOKEVIRTUAL, owner:java/lang/Object, name:getClass, desc:()Ljava/lang/Class; visitVarInsn, opcode:ASTORE,var:3 visitLabel, label:L2055281021 visitLineNumber, line:20, start label:20 visitInsn, opcode:ACONST_NULL visitVarInsn, opcode:ASTORE,var:4 visitLabel, label:L1554547125 visitLineNumber, line:21, start label:21 visitInsn, opcode:ACONST_NULL visitVarInsn, opcode:ASTORE,var:5 visitLabel, label:L617901222 visitLineNumber, line:22, start label:22 visitInsn, opcode:ACONST_NULL visitVarInsn, opcode:ASTORE,var:6 visitLabel, label:L1159190947 visitLineNumber, line:23, start label:23 visitVarInsn, opcode:ALOAD,var:3 visitLdcInsn, cst:Lcom/sample/app/MainActivity; visitJumpInsn, opcode:IF_ACMPNE, label:L681842940 visitLabel, label:L1392838282 visitLineNumber, line:24, start label:24 visitLdcInsn, cst:Lcom/sample/app/MainActivity$a; visitVarInsn, opcode:ASTORE,var:4 visitLabel, label:L523429237 visitLineNumber, line:25, start label:25 visitLdcInsn, cst:Lcom/a/a/d/a; visitVarInsn, opcode:ASTORE,var:5 visitLabel, label:L664740647 visitLineNumber, line:26, start label:26 visitLdcInsn, cst:showMessage visitVarInsn, opcode:ASTORE,var:6 visitLabel, label:L804564176 visitLineNumber, line:27, start label:27 visitVarInsn, opcode:ALOAD,var:2 visitVarInsn, opcode:ALOAD,var:6 visitVarInsn, opcode:ALOAD,var:4 visitVarInsn, opcode:ALOAD,var:5 visitTypeInsn, opcode:NEW, type:com/eventbus/gen/a visitInsn, opcode:DUP visitVarInsn, opcode:ALOAD,var:0 visitVarInsn, opcode:ALOAD,var:1 visitVarInsn, opcode:ALOAD,var:6 visitVarInsn, opcode:ALOAD,var:4 visitVarInsn, opcode:ALOAD,var:5 visitMethodInsn, opcode:INVOKESPECIAL, owner:com/eventbus/gen/a, name: , desc:(Lcom/eventbus/gen/BusIndex;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)V visitMethodInsn, opcode:INVOKEVIRTUAL, owner:com/a/a/c/d, name:a, desc:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Lcom/a/a/b/a;)V visitLabel, label:L1421795058 visitLineNumber, line:33, start label:33 visitLdcInsn, cst:Lcom/sample/app/MainActivity$a; visitVarInsn, opcode:ASTORE,var:4 visitLabel, label:L1555009629 visitLineNumber, line:34, start label:34 visitLdcInsn, cst:Lcom/a/a/d/a; visitVarInsn, opcode:ASTORE,var:5 visitLabel, label:L41359092 visitLineNumber, line:35, start label:35 visitLdcInsn, cst:showMessagedd visitVarInsn, opcode:ASTORE,var:6 visitLabel, label:L149928006 visitLineNumber, line:36, start label:36 visitVarInsn, opcode:ALOAD,var:2 visitVarInsn, opcode:ALOAD,var:6 visitVarInsn, opcode:ALOAD,var:4 visitVarInsn, opcode:ALOAD,var:5 visitTypeInsn, opcode:NEW, type:com/eventbus/gen/b visitInsn, opcode:DUP visitVarInsn, opcode:ALOAD,var:0 visitVarInsn, opcode:ALOAD,var:1 visitVarInsn, opcode:ALOAD,var:6 visitVarInsn, opcode:ALOAD,var:4 visitVarInsn, opcode:ALOAD,var:5 visitMethodInsn, opcode:INVOKESPECIAL, owner:com/eventbus/gen/b, name: , desc:(Lcom/eventbus/gen/BusIndex;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)V visitMethodInsn, opcode:INVOKEVIRTUAL, owner:com/a/a/c/d, name:a, desc:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Lcom/a/a/b/a;)V visitLabel, label:L713338599 visitLineNumber, line:42, start label:42 visitVarInsn, opcode:ALOAD,var:2 visitInsn, opcode:ARETURN visitLabel, label:L681842940 visitLineNumber, line:44, start label:44 visitVarInsn, opcode:ALOAD,var:3 visitLdcInsn, cst:Lcom/sample/app/Main2Activity; visitJumpInsn, opcode:IF_ACMPNE, label:L168423058 visitLabel, label:L821270929 visitLineNumber, line:45, start label:45 visitLdcInsn, cst:Lcom/sample/app/MainActivity$a; visitVarInsn, opcode:ASTORE,var:4 visitLabel, label:L1160460865 visitLineNumber, line:46, start label:46 visitLdcInsn, cst:Lcom/a/a/d/a; visitVarInsn, opcode:ASTORE,var:5 visitLabel, label:L1247233941 visitLineNumber, line:47, start label:47 visitLdcInsn, cst:showMessage visitVarInsn, opcode:ASTORE,var:6 visitLabel, label:L258952499 visitLineNumber, line:48, start label:48 visitVarInsn, opcode:ALOAD,var:2 visitVarInsn, opcode:ALOAD,var:6 visitVarInsn, opcode:ALOAD,var:4 visitVarInsn, opcode:ALOAD,var:5 visitTypeInsn, opcode:NEW, type:com/eventbus/gen/c visitInsn, opcode:DUP visitVarInsn, opcode:ALOAD,var:0 visitVarInsn, opcode:ALOAD,var:1 visitVarInsn, opcode:ALOAD,var:6 visitVarInsn, opcode:ALOAD,var:4 visitVarInsn, opcode:ALOAD,var:5 visitMethodInsn, opcode:INVOKESPECIAL, owner:com/eventbus/gen/c, name: , desc:(Lcom/eventbus/gen/BusIndex;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)V visitMethodInsn, opcode:INVOKEVIRTUAL, owner:com/a/a/c/d, name:a, desc:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Lcom/a/a/b/a;)V visitLabel, label:L603742814 visitLineNumber, line:54, start label:54 visitLdcInsn, cst:Lcom/sample/app/MainActivity$a; visitVarInsn, opcode:ASTORE,var:4 visitLabel, label:L1067040082 visitLineNumber, line:55, start label:55 visitLdcInsn, cst:Lcom/a/a/d/a; visitVarInsn, opcode:ASTORE,var:5 visitLabel, label:L1325547227 visitLineNumber, line:56, start label:56 visitLdcInsn, cst:showMessagedd visitVarInsn, opcode:ASTORE,var:6 visitLabel, label:L980546781 visitLineNumber, line:57, start label:57 visitVarInsn, opcode:ALOAD,var:2 visitVarInsn, opcode:ALOAD,var:6 visitVarInsn, opcode:ALOAD,var:4 visitVarInsn, opcode:ALOAD,var:5 visitTypeInsn, opcode:NEW, type:com/eventbus/gen/d visitInsn, opcode:DUP visitVarInsn, opcode:ALOAD,var:0 visitVarInsn, opcode:ALOAD,var:1 visitVarInsn, opcode:ALOAD,var:6 visitVarInsn, opcode:ALOAD,var:4 visitVarInsn, opcode:ALOAD,var:5 visitMethodInsn, opcode:INVOKESPECIAL, owner:com/eventbus/gen/d, name: , desc:(Lcom/eventbus/gen/BusIndex;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)V visitMethodInsn, opcode:INVOKEVIRTUAL, owner:com/a/a/c/d, name:a, desc:(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Lcom/a/a/b/a;)V visitLabel, label:L2061475679 visitLineNumber, line:63, start label:63 visitVarInsn, opcode:ALOAD,var:2 visitInsn, opcode:ARETURN visitLabel, label:L168423058 visitLineNumber, line:65, start label:65 visitVarInsn, opcode:ALOAD,var:2 visitInsn, opcode:ARETURN visitEnd visitor method ended. visitEnd 3.6.4 从结果中可以看出visitor method begin与visitor method ended之间输出的就是generateSubscribeMethodIndex的具体信息