字节码类库之Javassist
2024-10-08 22:38:37
Javassist优势
– 比反射开销小,性能高。
–javassist性能高于反射,低于ASM
运行时操作字节码可以让我们实现如下功能:
– 动态生成 新的类
– 动态改变某个类的结构 ( 添加 / 删除 / 修改 新的属性 / 方法 )
javassist 的最外层的 API 和 JAVA 的反射包中的 API 颇为 类似 。
它 主要 由 CtClass , CtMethod, ,以及 CtField 几个类组成。用以执行和 JDK 反射 API 中 java.lang.Class, java.lang.reflect.Method, java.lang.reflect.Method .Field 相同的 操作 。
方法操作
– 修改已有方法的方法体(插入代码到已有方法体)
– 新增方法 删除方法
javassist的局限性
JDK5.0 新语法不支持 ( 包括泛型、枚举 ) ,不支持注解修改,但可以通过底层的 javassist 类来解决,具体参考: javassist.bytecode.annotation
不支持数组的初始化,如 String[]{"1","2"} ,除非只有数组的容量为 1
不支持内部类和匿名类
不支持 continue 和 break表达式。
对于继承关系,有些不支持。例如
class A {}
class B extends A {}
class C extends B {}
创建类:
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewConstructor; public class App { public static void main(String[] args) throws Exception {
// 利用javassist 创建类 ClassPool poll = ClassPool.getDefault();
// 创建类名 全路径
CtClass ctClass = poll.makeClass("com.hella.thread.jvm.javassist.User");
// 创建属性
CtField name = CtField.make("private String name;", ctClass);
CtField age = CtField.make("private String age;", ctClass); // 属性添加到类中
ctClass.addField(name);
ctClass.addField(age); // 创建get set 方法
CtMethod getName = CtMethod.make("public void getName(){return name;}", ctClass);
CtMethod setName = CtMethod.make("public void setName(String name) {this.name = name;}", ctClass);
CtMethod getAge = CtMethod.make("public String getAge() {return age;}", ctClass);
CtMethod setAge = CtMethod.make("public void setAge(String age) {this.age = age;}", ctClass); // 方法添加到类中
ctClass.addMethod(getName);
ctClass.addMethod(setName);
ctClass.addMethod(getAge);
ctClass.addMethod(setAge); // 创建构造方法
CtConstructor constructor = CtNewConstructor
.make("public User(String name, String age) { this.name = name;this.age = age;}", ctClass); ctClass.addConstructor(constructor); // 生成的位置
ctClass.writeFile("C:/Users/caich5/Desktop/test");
} }
修改类的信息
public class User { private String name; private String age; // 通过字节码技术,在这个类添加以下的方法 // public int calcute(int a,int b){
// return a + b;
// } }
修改并且执行:
import java.lang.reflect.Method; import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod; public class Test {
public static void main(String[] args) throws Exception { ClassPool poll = ClassPool.getDefault();
// 获取到class
CtClass ctClass = poll.get("com.hella.thread.jvm.javassist.User");
CtMethod ctMethod = CtMethod.make("public int calcute(int a,int b){ return a + b ;}", ctClass);
ctClass.addMethod(ctMethod);
ctClass.writeFile("C:/Users/caich5/Desktop/test"); // 使用反射执行
Class<?> clazz = ctClass.toClass();
Object newInstance = clazz.newInstance();
Method method = clazz.getDeclaredMethod("calcute", int.class, int.class);
Object res = method.invoke(newInstance, 1, 2);
System.out.println(res); // 需要添加的方法 也可以这样写
// CtMethod m = new CtMethod(CtClass.intType, "add", new CtClass[] {
// CtClass.intType, CtClass.intType },
// userClass);
// // 方法权限
// m.setModifiers(Modifier.PUBLIC);
// // 方法体内容
// m.setBody("{System.out.println(\"Test003\"); return $1+$2;}");
} }
最新文章
- canvas arcTo()用法详解
- centos7 打开mysql 3306端口并 设置外部访问
- 基于CkEditor实现.net在线开发之路(3)常用From表单控件介绍与说明
- 代码阅读工具:Source Navigator和Source Insight
- centos6.7 mutlipath install script
- Nginx问题定位之监控进程异常退出
- AC日记—— codevs 1031 质数环(搜索)
- input绑定datapicker控件后input再绑定blur或者mouseout等问题
- H桥电路
- 结对开发--课堂练习--c++
- 函数buf_LRU_get_free_only
- elecworks 电缆型号管理器
- 在JSP页面中调用另一个JSP页面中的变量
- [OpenNebula]中间件訪问驱动程序
- centos 6.5下安装文件上传下载服务
- Qt 如何使用 QImage 设置指定的颜色为透明色?
- Java进阶(二)文件读操作
- 详解 JSONP跨域请求的实现
- 洛谷 P1691 有重复元素的排列问题 解题报告
- 还是Go 为了伟大的未来
热门文章
- java ThreadPoolExecutor初探
- SpringCloud Ribbon组成和负载均衡规则
- java集合-set
- Java工作流引擎结合可视化表单开发,10分钟完成一个业务流程发布
- NLP(二十二)利用ALBERT实现文本二分类
- PHP5.6.23+Apache2.4.20+Eclipse for PHP 4.5开发环境配置
- Python学习字典.基础三
- scrapy中间件中使用selenium切换ip
- 关于beforeRouteEnter中的next()
- Java并发编程学习前期知识下篇