简书链接:玩转javabytecode第一篇从java到asm的转换。
文章字数:550,阅读全文大约需要2分钟
java源码

1
2
3
4
5
6
7
public class SimpleMain {
public static void main(String[] args){
System.out.println("333:");

}
}

javap反汇编
javap -p -c -s -l TestAsmTrans.class

显示本地变量表 ```-c``` 反汇编
1
2
```
E:\eclipse_workspace\TestAsm\bin>javap -p -c -s -l TestAsmTrans.class

结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Compiled from "TestAsmTrans.java"
public class TestAsmTrans {
public TestAsmTrans();
descriptor: ()V
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 2: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LTestAsmTrans;

public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
Code:
0: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #22 // String 333:
5: invokevirtual #24 // Method java/io/PrintStream.println:(Ljava/lang/Stri
8: return
LineNumberTable:
line 4: 0
line 6: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 args [Ljava/lang/String;
}

E:\eclipse_workspace\TestAsm\bin>

转换为更加容易看懂的代码
eclipse下载byptecode view插件
image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class TestAsmTrans {

// compiled from: TestAsmTrans.java

// access flags 0x1
public <init>()V
L0
LINENUMBER 2 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this LTestAsmTrans; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1

// access flags 0x9
public static main([Ljava/lang/String;)V
L0
LINENUMBER 4 L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "333:"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L1
LINENUMBER 6 L1
RETURN
L2
LOCALVARIABLE args [Ljava/lang/String; L0 L2 0
MAXSTACK = 2
MAXLOCALS = 1
}

asm转换。

L0就表示label0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
ClassWriter classWriter = new ClassWriter(0);
FieldVisitor fieldVisitor;
MethodVisitor methodVisitor;
AnnotationVisitor annotationVisitor0;

classWriter.visit(V1_8, ACC_PUBLIC | ACC_SUPER, "test/SimpleMain", null, "java/lang/Object", null);

classWriter.visitSource("SimpleMain.java", null);

{
methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
methodVisitor.visitCode();
Label label0 = new Label();
methodVisitor.visitLabel(label0);
methodVisitor.visitLineNumber(7, label0);
methodVisitor.visitVarInsn(ALOAD, 0);
methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
methodVisitor.visitInsn(RETURN);
Label label1 = new Label();
methodVisitor.visitLabel(label1);
methodVisitor.visitLocalVariable("this", "Ltest/SimpleMain;", null, label0, label1, 0);
methodVisitor.visitMaxs(1, 1);
methodVisitor.visitEnd();
}
{
methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
methodVisitor.visitCode();
Label label0 = new Label();
methodVisitor.visitLabel(label0);
methodVisitor.visitLineNumber(9, label0);
methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
methodVisitor.visitLdcInsn("333:");
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
Label label1 = new Label();
methodVisitor.visitLabel(label1);
methodVisitor.visitLineNumber(11, label1);
methodVisitor.visitInsn(RETURN);
Label label2 = new Label();
methodVisitor.visitLabel(label2);
methodVisitor.visitLocalVariable("args", "[Ljava/lang/String;", null, label0, label2, 0);
methodVisitor.visitMaxs(2, 1);
methodVisitor.visitEnd();
}
classWriter.visitEnd();

return classWriter.toByteArray();
}
}

调用顺序

1
2
3
* visit visitSource? visitOuterClass? ( visitAnnotation | visitAttribute )*( visitInnerClass | visitField |
* visitMethod )*
* visitEnd

更多操作

java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class TestIntByte {
@Test
public void test() {
System.out.println(new int[]{133333333, 66663, 4666663, 533333, 633333333});
}

@Test
public void testCharByInt() {
System.out.println(new char[]{(char) 5, (char) 6, (char) 7, (char) 333});
}

@Test
public void testChar1() {
System.out.println(new char[]{'b', 'd', 'n', 'a'});
}

@Test
public void testLong() {
System.out.println(new long[]{100l,600l,15550l,3330l});
}


@Test
public void testFloat() {
System.out.println(new float[]{100.0f,600f,15550f,3330f});
}
}

asm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
F:\src\git_project\RXJavaStudy\tools\asm-all-6.0_BETA>java -cp asm-6.0.jar org.objectweb.asm.util.ASMifier TestIntByte.class
import java.util.*;
import org.objectweb.asm.*;
public class TestIntByteDump implements Opcodes {

public static byte[] dump () throws Exception {

ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;

cw.visit(V1_8, ACC_SUPER, "TestIntByte", null, "java/lang/Object", null);

{
mv = cw.visitMethod(0, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC, "test", "()V", null, null);
{
av0 = mv.visitAnnotation("Lorg/junit/Test;", true);
av0.visitEnd();
}
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitInsn(ICONST_5);
mv.visitIntInsn(NEWARRAY, T_INT);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_0);
mv.visitLdcInsn(new Integer(133333333));
mv.visitInsn(IASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_1);
mv.visitLdcInsn(new Integer(66663));
mv.visitInsn(IASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_2);
mv.visitLdcInsn(new Integer(4666663));
mv.visitInsn(IASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_3);
mv.visitLdcInsn(new Integer(533333));
mv.visitInsn(IASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_4);
mv.visitLdcInsn(new Integer(633333333));
mv.visitInsn(IASTORE);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/Object;)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(5, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC, "testCharByInt", "()V", null, null);
{
av0 = mv.visitAnnotation("Lorg/junit/Test;", true);
av0.visitEnd();
}
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitInsn(ICONST_4);
mv.visitIntInsn(NEWARRAY, T_CHAR);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_0);
mv.visitInsn(ICONST_5);
mv.visitInsn(CASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_1);
mv.visitIntInsn(BIPUSH, 6);
mv.visitInsn(CASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_2);
mv.visitIntInsn(BIPUSH, 7);
mv.visitInsn(CASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_3);
mv.visitIntInsn(SIPUSH, 333);
mv.visitInsn(CASTORE);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "([C)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(5, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC, "testChar1", "()V", null, null);
{
av0 = mv.visitAnnotation("Lorg/junit/Test;", true);
av0.visitEnd();
}
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitInsn(ICONST_4);
mv.visitIntInsn(NEWARRAY, T_CHAR);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_0);
mv.visitIntInsn(BIPUSH, 98);
mv.visitInsn(CASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_1);
mv.visitIntInsn(BIPUSH, 100);
mv.visitInsn(CASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_2);
mv.visitIntInsn(BIPUSH, 110);
mv.visitInsn(CASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_3);
mv.visitIntInsn(BIPUSH, 97);
mv.visitInsn(CASTORE);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "([C)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(5, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC, "testLong", "()V", null, null);
{
av0 = mv.visitAnnotation("Lorg/junit/Test;", true);
av0.visitEnd();
}
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitInsn(ICONST_4);
mv.visitIntInsn(NEWARRAY, T_LONG);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_0);
mv.visitLdcInsn(new Long(100L));
mv.visitInsn(LASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_1);
mv.visitLdcInsn(new Long(600L));
mv.visitInsn(LASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_2);
mv.visitLdcInsn(new Long(15550L));
mv.visitInsn(LASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_3);
mv.visitLdcInsn(new Long(3330L));
mv.visitInsn(LASTORE);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/Object;)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(6, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC, "testFloat", "()V", null, null);
{
av0 = mv.visitAnnotation("Lorg/junit/Test;", true);
av0.visitEnd();
}
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitInsn(ICONST_4);
mv.visitIntInsn(NEWARRAY, T_FLOAT);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_0);
mv.visitLdcInsn(new Float("100.0"));
mv.visitInsn(FASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_1);
mv.visitLdcInsn(new Float("600.0"));
mv.visitInsn(FASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_2);
mv.visitLdcInsn(new Float("15550.0"));
mv.visitInsn(FASTORE);
mv.visitInsn(DUP);
mv.visitInsn(ICONST_3);
mv.visitLdcInsn(new Float("3330.0"));
mv.visitInsn(FASTORE);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/Object;)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(5, 1);
mv.visitEnd();
}
cw.visitEnd();

return cw.toByteArray();
}
}

更多技巧使用 官网的工具
https://asm.ow2.io/javadoc/overview-summary.html

可以方便快捷的查看,可惜,我当时在公司研究忘记上传github了,当时是做了一个脚本来着
可以边写边预览源代码。