在学习ASM的时候,找到IBM网站的一文章,不知怎搞的就是没通过。或许习惯了代码,总希望不管三七二一先在Eclipse跑了再说,看看效果。再加上刚接触ASM不熟悉,例子硬生生跑不了,确实令人苦恼。
一下贴出完整例子
public class Generator{
public static void main(String[] args) throws Exception {
SecureAccountGenerator s = new SecureAccountGenerator();
s.generateSecureAccount().operation();
}
}
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
public class SecureAccountGenerator {
private static AccountGeneratorClassLoader classLoader = new AccountGeneratorClassLoader();
private static Class secureAccountClass;
public Account generateSecureAccount() throws ClassFormatError,
InstantiationException, IllegalAccessException {
if (null == secureAccountClass) {
ClassReader cr;
try {
String className ="Account$EnhancedByASM";
cr = new ClassReader("Account");
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassAdapter classAdapter = new AddSecurityCheckClassAdapter(cw);
cr.accept(classAdapter, ClassReader.SKIP_DEBUG);
byte[] data = cw.toByteArray();
secureAccountClass = classLoader.defineClassFromClassFile( className, data);
} catch (Exception e) {
e.printStackTrace();
}
}
return (Account) secureAccountClass.newInstance();
}
private static class AccountGeneratorClassLoader extends ClassLoader {
public Class defineClassFromClassFile(String className, byte[] classFile) throws ClassFormatError {
return defineClass(className, classFile, 0,classFile.length);
}
}
}
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
class AddSecurityCheckClassAdapter extends ClassAdapter {
public AddSecurityCheckClassAdapter(ClassVisitor cv) {
// Responsechain 的下一个 ClassVisitor,这里我们将传入 ClassWriter,
// 负责改写后代码的输出
super(cv);
}
// 重写 visitMethod,访问到 "operation" 方法时,
// 给出自定义 MethodVisitor,实际改写方法内容
public MethodVisitor visitMethod(
final int access, final String name,final String desc, final String signature, final String[] exceptions) {
MethodVisitor mv = cv.visitMethod(access, name, desc, signature,exceptions );
MethodVisitor wrappedMv = mv;
String enhancedSuperName = "Account";
if (mv != null) {
if (name.equals("operation")) {
wrappedMv = new AddSecurityCheckMethodAdapter(mv);
} else if (name.equals("<init>")) {
wrappedMv = new ChangeToChildConstructorMethodAdapter(mv,enhancedSuperName);
}
}
return wrappedMv;
}
public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) {
// String enhancedName = name + "$EnhancedByASM"; //改变类命名
// System.out.println("visit name:"+signature);
String enhancedSuperName = name; //改变父类,这里是”Account”
String enhancedName = "Account$EnhancedByASM";//改变类命名
super.visit(version, access, enhancedName, signature,enhancedSuperName, interfaces);
}
}
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
class AddSecurityCheckMethodAdapter extends MethodAdapter {
public AddSecurityCheckMethodAdapter(MethodVisitor mv) {
super(mv);
}
public void visitCode() {
visitMethodInsn(Opcodes.INVOKESTATIC, "SecurityChecker","checkSecurity", "()V");
}
}
class ChangeToChildConstructorMethodAdapter extends MethodAdapter {
private String superClassName;
public ChangeToChildConstructorMethodAdapter(MethodVisitor mv,String superClassName) {
super(mv);
this.superClassName = superClassName;
}
public void visitMethodInsn(int opcode, String owner, String name,String desc) {
// 如果当前指令是调用父类的构造方法
// mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
if (opcode == Opcodes.INVOKESPECIAL && name.equals("<init>")) {
owner = superClassName;
}
super.visitMethodInsn(opcode, owner, name, desc);// 改写父类为superClassName
}
}
public class SecurityChecker {
public static void checkSecurity() {
System.out.println("SecurityChecker.checkSecurity ...");
}
}
public class Account {
public void operation() {
System.out.println("operation...");
}
}