使用ASM生成Java字节码(可以通过代码动态生成java字节码)


使用ASM生成Java字节码,下面通过java程序模拟实现spring aop 动态织入

 

Account.java

 1 package com.market.search.test;
 2 
 3 /**
 4  * Created by xiaotian on 2018/5/8.
 5  */
 6 public class Account {
 7     public void operation() {
 8         //通过字节码生成技术 动态添加check功能  模拟aop 动态织入
 9         System.out.println("operation....");
10     }
11 
12 }

SecurityChecker.java

 1 package com.market.search.test;
 2 
 3 /**
 4  * Created by xiaotian on 2018/5/8.
 5  * 将checkSecurity 通过ASE方式动态 增强Account.operation 中
 6  */
 7 public class SecurityChecker {
 8 
 9     public static boolean checkSecurity() {
10         System.out.println("SecurityChecker.checkSecurity ...");
11         return true;
12     }
13 
14 }

AddSecurityCheckClassAdapter.java  类适配

 1 package com.market.search.test;
 2 
 3 import jdk.internal.org.objectweb.asm.ClassVisitor;
 4 import jdk.internal.org.objectweb.asm.MethodVisitor;
 5 import jdk.internal.org.objectweb.asm.Opcodes;
 6 
 7 /**
 8  * Created by xiaotian on 2018/5/8.
 9  */
10 public class AddSecurityCheckClassAdapter extends ClassVisitor {
11     public AddSecurityCheckClassAdapter( ClassVisitor cv) {
12         super(Opcodes.ASM5, cv);
13     }
14     // 重写 visitMethod,访问到 "operation" 方法时,
15     // 给出自定义 MethodVisitor,实际改写方法内容
16     public MethodVisitor visitMethod(final int access, final String name,
17                                      final String desc, final String signature, final String[] exceptions) {
18         MethodVisitor mv = cv.visitMethod(access, name, desc, signature,exceptions);
19         MethodVisitor wrappedMv = mv;
20         if (mv != null) {
21             // 对于 "operation" 方法
22             if (name.equals("operation")) {
23                 // 使用自定义 MethodVisitor,实际改写方法内容
24                 wrappedMv = new AddSecurityCheckMethodAdapter(mv);
25             }
26         }
27         return wrappedMv;
28     }
29 
30 }

AddSecurityCheckMethodAdapter.java 方法适配

 1 package com.market.search.test;
 2 
 3 import jdk.internal.org.objectweb.asm.MethodVisitor;
 4 import jdk.internal.org.objectweb.asm.Opcodes;
 5 
 6 /**
 7  * Created by xiaotian on 2018/5/8.
 8  */
 9 public class AddSecurityCheckMethodAdapter extends MethodVisitor {
10     public AddSecurityCheckMethodAdapter(MethodVisitor mv) {
11         super(Opcodes.ASM5,mv);
12     }
13     public void visitCode() {
14         visitMethodInsn(Opcodes.INVOKESTATIC, "com/market/search/test/SecurityChecker",
15                 "checkSecurity", "()Z");
16         super.visitCode();
17     }
18 
19 }
Generator.java  测试生成字节码
 1 package com.market.search.test;
 2 
 3 import jdk.internal.org.objectweb.asm.ClassReader;
 4 import jdk.internal.org.objectweb.asm.ClassWriter;
 5 
 6 import java.io.File;
 7 import java.io.FileOutputStream;
 8 import java.net.URL;
 9 import java.net.URLClassLoader;
10 
11 /**
12  * Created by xiaotian on 2018/5/8.
13  */
14 public class Generator {
15     private static AccountGeneratorClassLoader classLoader = new AccountGeneratorClassLoader();
16     public static void main(String args[]) throws Exception {
17         ClassReader cr = new ClassReader("com.market.search.test.Account");
18         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS|ClassWriter.COMPUTE_FRAMES);
19         AddSecurityCheckClassAdapter classAdapter = new AddSecurityCheckClassAdapter(cw);
20         cr.accept(classAdapter, ClassReader.SKIP_DEBUG);
21 
22         byte[] data = cw.toByteArray();
23         //File file = new File("C:\\Users\\xiaotian\\Desktop\\jvm原理\\Account.class");
24         File file = new File("D:\\devlop\\workspace.market.new\\market-search-main-BL\\search-service_1.0.2_BR\\target\\classes\\com\\market\\search\\test\\Account.class");
25         FileOutputStream fout = new FileOutputStream(file);
26         fout.write(data);
27         fout.close();
28 
29 //        Class account = classLoader.defineClassFromClassFile("com.market.search.test.Account", data);
30 //        Account acc =(Account) account.newInstance();
31 //        acc.operation();
32         Account account = new Account();
33         account.operation();
34 
35 
36     }
37     private static class AccountGeneratorClassLoader extends ClassLoader {
38         public Class defineClassFromClassFile(String className, byte[] classFile) throws ClassFormatError {
39             return defineClass(className, classFile, 0,classFile.length);
40         }
41     }
42 }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM