java动态字节码指的是在java字节码生成以后,对其进行修改,加强其功能,这种方式至关于对代码的二进制文件进行修改。动态java字节码主要是为了减小冗余代码,提升性能。java
实现字节码加强的主要步骤:数组
ASM
、Javaasist
)来修改它的byte[]数组,获得一个新的byte[]数组。ClassLoader
来加载修改后的字节码JVM
加载用户的Class
时,拦截返回修改后的字节码。用途bash
BCEL
能够深刻JVM
汇编语言进行类操做的细节。BCEL
与javassist
有不一样的处理字节码方法,BCEL
在实际的JVM
指令层次上进行操做,而javassist
所强调的是源代码级别的工做。框架
是轻量级java
字节码操做框架,直接涉及到JVM
底层的操做和指令。高性能,高质量maven
基于ASM
实现工具
性能低于ASM
跟CGLB
差很少,可是使用简单,不少开源框架都使用的是javassist
。javassist
比反射开销小,性能高。性能
javassist
的最外层的API
和JAVA
的反射包中的API
颇为类似。它主要由CtClass
、CtMethod
以及CtField
几个类组成,用以执行和JDK
反射API
中java.lang.Class
、java.lang.reflect.Method
、java.lang.reflect.Field
相同的操做。ui
局限性this
JDK5.0
新语法不支持(包括泛型、枚举),不支持注解修改continue
和break
表达式maven : mvnrepository.com/artifact/ja…spa
反射调用方法
public class User {
private String name;
private Integer age;
public void sum(int a,int b){
int sum = a + b;
System.out.println("sum = " + sum);
}
public static void main(String[] args) {
try {
Class<?> clz = Class.forName("javassist.User");
Object newInstance = clz.newInstance();
Method method = clz.getDeclaredMethod("sum", int.class, int.class);
Object invoke = method.invoke(newInstance, 1, 3);
}catch (Exception e){
}
}
}
复制代码
javassist
生成class
文件
//使用javassist建立class文件
ClassPool pool = ClassPool.getDefault();
//建立 class 文件
CtClass userClass = pool.makeClass("com.beisiji.javassist.User");
//建立 id 属性
CtField idField = CtField.make("private Integer id;", userClass);
//建立 name 属性
CtField nameField = CtField.make("private String name;", userClass);
//添加属性
userClass.addField(idField);
userClass.addField(nameField);
//建立方法
CtMethod setIdMethod = CtMethod.make("public void setId(Integer id) { this.id = id; }", userClass);
CtMethod getIdMethod = CtMethod.make("public Integer getId() { return id; }", userClass);
//添加方法
userClass.addMethod(setIdMethod);
userClass.addMethod(getIdMethod);
//建立构造器
CtConstructor ctConstructor = new CtConstructor(new CtClass[]{CtClass.intType, pool.get("java.lang.String")}, userClass);
ctConstructor.setBody("{ this.id = id;this.name = name; }");
userClass.addConstructor(ctConstructor);
userClass.writeFile("C:/Users/yuanl/Desktop/md_dir");
复制代码
javassist
修改类文件信息
//使用javassist修改类文件信息(添加方法)
ClassPool pool = ClassPool.getDefault();
//须要加载的类信息(须要修改类信息的全限定名称)
CtClass userClass = pool.get("executor.ExecutorDemo");
//建立方法
CtMethod method = new CtMethod(CtClass.intType, "add", new CtClass[]{CtClass.intType, CtClass.intType}, userClass);
//设置方法权限
method.setModifiers(Modifier.PUBLIC);
method.setBody("{return $1 + $2;}"); //$0:this , $1第一个参数 , $2第二个参数
userClass.addMethod(method);
userClass.writeFile("C:/Users/yuanl/Desktop/md_dir");
//调用添加的方法
Class clz = userClass.toClass();
Object newInstance = clz.newInstance();
Method addMethod = clz.getDeclaredMethod("add", int.class, int.class);
Object invoke = addMethod.invoke(newInstance, 2, 3);
System.out.println("invoke = " + invoke);
复制代码