forked from mood321/Java
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMethodAddCode.java
More file actions
148 lines (126 loc) · 5.17 KB
/
Copy pathMethodAddCode.java
File metadata and controls
148 lines (126 loc) · 5.17 KB
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
package dynamic.asm;
import clazz.MyClassLoader;
import com.sun.xml.internal.ws.util.StringUtils;
import dynamic.asm.bean.Demo;
import dynamic.asm.bean.Log;
import jdk.internal.org.objectweb.asm.*;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static jdk.internal.org.objectweb.asm.Opcodes.*;
public class MethodAddCode {
public static class AddCodeVisitor extends ClassVisitor {
public AddCodeVisitor(int i, ClassVisitor classVisitor) {
super(i, classVisitor);
}
/**
* 访问到方法时被调用
* @param access
* @param name
* @param descriptor
* @param signature
* @param exceptions
* @return
*/
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
//不代理构造函数
if(!"<init>".equals(name)) {
MethodVisitor mv = cv.visitMethod(access, name, descriptor, signature, exceptions);
//方式一
return new AddCodeMethodVisitor_1(this.api,mv);
//方式二
// return new AddCodeMethodVisitor_2(this.api,mv);
}
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
}
/**
* 方式一:通过字节编写字节码的方式织入代码
*/
public static class AddCodeMethodVisitor_1 extends MethodVisitor {
public AddCodeMethodVisitor_1(int api, MethodVisitor methodVisitor) {
super(api, methodVisitor);
}
/**方法的开始,即刚进入方法里面*/
@Override
public void visitCode() {
mv.visitFieldInsn(Opcodes.GETSTATIC,"java/lang/System","out","Ljava/io/PrintStream;");
mv.visitLdcInsn("方式一:方法开始运行");
mv.visitMethodInsn(INVOKEVIRTUAL,"java/io/PrintStream","println","(Ljava/lang/String;)V");
super.visitCode();
}
@Override
public void visitInsn(int opcode) {
if(opcode == ARETURN || opcode == RETURN ) {
mv.visitFieldInsn(Opcodes.GETSTATIC,"java/lang/System","out","Ljava/io/PrintStream;");
mv.visitLdcInsn("方式一:方法调用结束");
mv.visitMethodInsn(INVOKEVIRTUAL,"java/io/PrintStream","println","(Ljava/lang/String;)V");
}
super.visitInsn(opcode);
}
@Override
public void visitEnd() {
mv.visitMaxs(6,6);
super.visitEnd();
}
}
/**
* 方式二:通过调用现有的class文件
*/
public static class AddCodeMethodVisitor_2 extends MethodVisitor {
public AddCodeMethodVisitor_2(int api, MethodVisitor methodVisitor) {
super(api, methodVisitor);
}
/**方法的开始,即刚进入方法里面*/
@Override
public void visitCode() {
mv.visitMethodInsn(INVOKESTATIC, Log.class.getName().replace(".","/"),"beforeMethod","()V",false);
super.visitCode();
}
@Override
public void visitInsn(int opcode) {
if(opcode == ARETURN || opcode == RETURN ) {
mv.visitMethodInsn(INVOKESTATIC,Log.class.getName().replace(".","/"),"afterMethod","()V",false);
}
super.visitInsn(opcode);
}
@Override
public void visitEnd() {
mv.visitMaxs(6,6);
super.visitEnd();
}
}
public static void main(String[] args) throws IOException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
String fullName = Demo.class.getName();
String fullNameType = fullName.replace(".", "/");
ClassReader cr = new ClassReader(fullNameType);
ClassWriter cw = new ClassWriter(0);
AddCodeVisitor cv = new AddCodeVisitor(Opcodes.ASM5,cw);
cr.accept(cv,ClassReader.SKIP_DEBUG);
byte[] bytes = cw.toByteArray();
try {
FileOutputStream fos = new FileOutputStream(Demo.class.getClassLoader().getResource("dynamic/asm/bean/Demo.class").getFile()); // 将二进制流写到本地磁盘上
fos.write(bytes);
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
/* MyClassLoader classLoader = new MyClassLoader();
Class<?> cls = classLoader.defineClassPublic(fullName, bytes, 0, bytes.length);*/
try {
//不重新加载
// Class cls = Class.forName("dynamic.asm.bean.Demo");
//一样 已有不重新加载
// Class cls = Demo.class.getClassLoader().loadClass("dynamic.asm.bean.Demo");
MyClassLoader myClassLoader = new MyClassLoader();
Class cls = myClassLoader.findClass("dynamic.asm.bean.Demo");
Object o = cls.newInstance();
Method getDemoInfo = cls.getMethod("getDemoInfo");
getDemoInfo.invoke(o);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}