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);
複製代碼