摘要:因此,若想对对象进行修改,必须对其进行解冻,通过方法进行生成一个方法生成一个方法通过反射调用生成的方法方法体前面和后面加执行语句方法体前面通过反射调用生成的方法张三生成属性和方法获取属性生成构造器可以在构造器前后加代码注解操作
Java知识点总结(动态字节码操作-Javassist的API使用)
@(Java知识点总结)[Java, 动态字节码操作]
参考文章: 传送
操作示例:
public @interface Author { String name(); int year(); }
@Author(name = "gs",year=2015) public class Emp { private int num; private String name; public Emp() { } public Emp(int num, String name) { this(); this.num = num; this.name = name; } public void sayHello(String name){ System.out.print("你好,"); } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor; import javassist.CtField; import javassist.CtMethod; import javassist.CtNewMethod; import javassist.NotFoundException; /** * 测试 javassist 的 API * * @author Administrator * */ public class Test11 { // 通过类名加载已有的类 public static void test1(ClassPool pool, CtClass cc) { try { cc = pool.get("com.gs.Emp"); byte[] bytes = cc.toBytecode(); // 转化为字节码 System.out.println(Arrays.toString(bytes)); System.out.println(cc.getName()); // 获取类名 System.out.println(cc.getSimpleName()); System.out.println(cc.getSuperclass()); // 获取父类 System.out.println(cc.getInterfaces()); // 获取接口 } catch (Exception e) { e.printStackTrace(); } } // 动态生成一个方法,并调用 public static void test2(ClassPool pool, CtClass cc) { try { /*当CtClass对象通过writeFile()、toClass()、toBytecode()转化为Class后, * Javassist冻结了CtClass对象,因此,JVM不允许再次加载Class文件,所以不允许对其修改。 因此,若想对CtClass对象进行修改,必须对其进行解冻,通过defrost()方法进行*/ cc.defrost(); // 生成一个方法 CtMethod add = CtNewMethod.make("public int add(int a,int b){return $1+$2;}", cc); // 生成一个方法 CtMethod subtraction = new CtMethod(CtClass.intType, "subtraction", new CtClass[] { CtClass.intType, CtClass.intType }, cc); subtraction.setModifiers(Modifier.PUBLIC); subtraction.setBody("return $1-$2;"); cc.addMethod(add); cc.addMethod(subtraction); // 通过反射调用生成的方法 Class clazz = cc.toClass(); Emp emp = (Emp) clazz.newInstance(); // Method method = clazz.getDeclaredMethod("add", new // Class[]{int.class,int.class}); Method method = clazz.getDeclaredMethod("subtraction", new Class[] { int.class, int.class }); Object result = method.invoke(emp, 200, 300); System.out.println(result); } catch (Exception e) { } } // 方法体前面和后面加执行语句 public static void test3(ClassPool pool, CtClass cc) { try { cc.defrost(); CtMethod m1 = cc.getDeclaredMethod("sayHello", new CtClass[] { pool.get("java.lang.String") }); m1.insertBefore("System.out.println("方法体前面");"); m1.insertAfter("System.out.println($1);"); // 通过反射调用生成的方法 Class clazz = cc.toClass(); Emp emp = (Emp) clazz.newInstance(); Method method = clazz.getDeclaredMethod("sayHello", new Class[] { String.class }); method.invoke(emp, "张三"); } catch (Exception e) { e.printStackTrace(); } } // 生成属性和方法 public static void test4(ClassPool pool, CtClass cc) { try { // CtField.make("private double salary;", cc); CtField field = new CtField(CtClass.doubleType, "salary", cc); field.setModifiers(Modifier.PRIVATE); cc.addField(field); // cc.getDeclaredField("salary"); //获取属性 CtMethod method = CtNewMethod.getter("getSalary", field); cc.addMethod(method); CtMethod method2 = CtNewMethod.getter("setSalary", field); cc.addMethod(method2); } catch (Exception e) { e.printStackTrace(); } } // 生成构造器 public static void test5(ClassPool pool, CtClass cc) { try { cc.defrost(); CtConstructor[] cs = cc.getConstructors(); for (CtConstructor c : cs) { System.out.println(c.getLongName()); c.insertAfter("System.out.println("可以在构造器前后加代码");"); } } catch (Exception e) { e.printStackTrace(); } } // 注解操作 public static void test6(ClassPool pool, CtClass cc) { try { cc.defrost(); Object[] annotations = cc.getAnnotations(); Author author = (Author) annotations[0]; System.out.println("name:" + author.name() + ",year:" + author.year()); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { ClassPool pool = ClassPool.getDefault(); CtClass cc = null; try { cc = pool.get("com.gs.Emp"); } catch (NotFoundException e) { e.printStackTrace(); } test1(pool, cc); //test2(pool, cc); test3(pool, cc); test5(pool, cc); test6(pool, cc); } }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/71625.html
摘要:知识点总结动态字节码操作介绍知识点总结动态字节码操作运行时操作字节码可以让我们实现如下功能动态生成新的类动态改变某个类的结构添加删除修改新的属性方法常见的字节码操作类库,这是的项目的一部分。 Java知识点总结(动态字节码操作-Javassist介绍) @(Java知识点总结)[Java, 动态字节码操作] 运行时操作字节码可以让我们实现如下功能: 动态生成新的类 动态改变某个类的结...
摘要:动态编程使用场景通过配置生成代码,减少重复编码,降低维护成本。动态生成字节码操作字节码的工具有,其中有两个比较流行的,一个是,一个是。 作者简介 传恒,一个喜欢摄影和旅游的软件工程师,先后从事饿了么物流蜂鸟自配送和蜂鸟众包的开发,现在转战 Java,目前负责物流策略组分流相关业务的开发。 什么是动态编程 动态编程是相对于静态编程而言的,平时我们讨论比较多的静态编程语言例如Java, 与动态...
摘要:字节码操作动态性的两种常见实现方式字节码操作反射运行时操作字节码可以让我们实现如下功能动态生成新的类动态改变某个类的结构添加删除修改新的属性方法优势比反射开销小性能高性能高于反射低于常见的字节码操作类库这是的项目的一部分是广泛使用的一种框它 1.字节码操作 JAVA动态性的两种常见实现方式字节码操作 反射 运行时操作字节码可以让我们实现如下功能动态生成新的类 动态改变某个类的结构(...
摘要:全称应用性能管理监控后面我会通过一系列的文章来介绍的原理框架设计与实现等等。在应用构建期间,通过修改字节码的方式来进行字节码插桩就是实现自动化的方案之一。 showImg(https://segmentfault.com/img/bVbbRX6?w=1995&h=1273); 欢迎关注微信公众号:BaronTalk,获取更多精彩好文! 一. 前言 性能问题是导致 App 用户流失的罪魁...
摘要:支持重试版本思考小明我手头还有其他任务,这个也挺简单的。与其他类似的字节码编辑器不同,提供了两个级别的源级和字节码级。另一方面,字节码级允许用户直接编辑类文件作为其他编辑器。提供与其他字节码框架类似的功能,但主要关注性能。 系列说明 java retry 的一步步实现机制。 java-retry 源码地址 情景导入 简单的需求 产品经理:实现一个按条件,查询用户信息的服务。 小明:好的...
阅读 3295·2021-11-12 10:36
阅读 2444·2021-11-02 14:43
阅读 2126·2019-08-30 14:23
阅读 3445·2019-08-30 13:08
阅读 906·2019-08-28 18:09
阅读 3109·2019-08-26 12:22
阅读 3081·2019-08-23 18:24
阅读 1992·2019-08-23 18:17