依赖
<!--
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-all</artifactId>
<version>5.2</version>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm-all</artifactId>
<version>3.3.1</version>
</dependency>
-->
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>7.1</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-commons</artifactId>
<version>7.1</version>
</dependency>
<!--
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-util</artifactId>
<version>7.1</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-test</artifactId>
<version>7.1</version>
</dependency>
-->
接口
public interface Person {
boolean getBoolean();
char getChar();
byte getByte();
short getShort();
int getInt();
float getFloat();
double getDouble();
long getLong();
String getName();
void setId();
int add(int a, int b);
Student getStudent(char[] vv);
Student[] getStudents(char[] vv);
Long getL();
Double getD();
MyEnum getMyEnum();
}
代码
import org.objectweb.asm.*;
import org.objectweb.asm.commons.AdviceAdapter;
import java.io.FileOutputStream;
import java.lang.reflect.Method;
public class AsmUtil implements Opcodes {
private static byte[] generateByteCode(Class<?> clazz) throws Exception {
ClassReader classReader = new ClassReader(clazz.getName());
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassVisitor interfaceClassVisitor = new InterfaceClassVisitor(classWriter, clazz);
classReader.accept(interfaceClassVisitor, ClassReader.SKIP_DEBUG);
//写入文件
byte[] code = classWriter.toByteArray();
/**
* 此3句打开会在当前生成一个class文件
* FileOutputStream fos = new FileOutputStream(getNewClassName(clazz) + ".class");
* fos.write(code);
* fos.close();
*/
return code;
}
private static class InterfaceClassVisitor extends ClassVisitor {
private Class<?> clazz;
public InterfaceClassVisitor(ClassVisitor classVisitor, Class<?> clazz) {
super(ASM7, classVisitor);
this.clazz = clazz;
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
String className = getNewClassName(clazz);
cv.visit(V1_8, ACC_PUBLIC, className, null, "java/lang/Object", new String[]{clazz.getName().replaceAll("\\.", "/")});
//生成默认构造函数
MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if ("<init>".equals(name)) {
MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions);
return methodVisitor;
}
MethodVisitor mv = cv.visitMethod(access - ACC_ABSTRACT, name, desc, signature, exceptions);
return new MethodAdviceAdapter(mv, access, name, desc);
}
}
private static class MethodAdviceAdapter extends AdviceAdapter {
private String descriptor;
protected MethodAdviceAdapter(MethodVisitor methodVisitor, int access, String name, String descriptor) {
super(ASM7, methodVisitor, access, name, descriptor);
this.descriptor = descriptor;
}
@Override
public void visitEnd() {
if (descriptor.endsWith("V")) {
mv.visitInsn(RETURN);
} else if (descriptor.endsWith("I") || descriptor.endsWith("Z") || descriptor.endsWith("C") || descriptor.endsWith("B") || descriptor.endsWith("S")) {
mv.visitInsn(ICONST_0);
mv.visitInsn(IRETURN);
} else if (descriptor.endsWith("F")) {
mv.visitInsn(FCONST_0);
mv.visitInsn(FRETURN);
} else if (descriptor.endsWith("D")) {
mv.visitInsn(DCONST_0);
mv.visitInsn(DRETURN);
} else if (descriptor.endsWith("J")) {
mv.visitInsn(LCONST_0);
mv.visitInsn(LRETURN);
} else {
mv.visitInsn(ACONST_NULL);
mv.visitInsn(ARETURN);
}
mv.visitMaxs(0, 0);
super.visitEnd();
}
}
public static Class getInterfaceImpl(Class clazz) throws Exception {
byte[] code = generateByteCode(clazz);
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class cls = Class.forName("java.lang.ClassLoader");
Method method = cls.getDeclaredMethod("defineClass", new Class[]{String.class, byte[].class, int.class, int.class});
method.setAccessible(true);
try {
Object[] args = new Object[]{getNewClassName(clazz), code, 0, code.length};
clazz = (Class) method.invoke(loader, args);
return clazz;
} finally {
method.setAccessible(false);
}
}
private static String getNewClassName(Class<?> clazz) {
return clazz.getSimpleName() + "Impl";
}
}