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(!"".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();
}
}
}