Java知識點總結(動態字節碼操做-Javassist介紹)

Java知識點總結(動態字節碼操做-Javassist介紹)

@(Java知識點總結)[Java, 動態字節碼操做]java

運行時操做字節碼可讓咱們實現以下功能:數組

  • 動態生成新的類
  • 動態改變某個類的結構(添加/刪除/修改 新的屬性/方法)

java常見的字節碼操做類庫

BCEL
  • Byte Code Engineering Library (BCEL) ,這是 Apache Software Foundation 的 Jakarta 項目的一部分。 BCEL 是 Java classworking 普遍 使用的一種 框架 , 它 可讓您深刻 JVM 彙編語言進行類操做的細節。 BCEL 與 Javassist 有不一樣的處理字節碼方法, BCEL 在實際的 JVM 指令層次上進行操做 (BCEL 擁有豐富的 JVM 指令級支持 ) 而 Javassist 所 強調 的是源代碼 級別的 工做 。
ASM
  • 是一個輕量級 java 字節碼操做框架,直接涉及到 JVM 底層的操做和 指令
CGLIB(Code Generation Library)

是一個強大的,高性能,高質量的 Code框架

Javassist

是 一個開源的分析、編輯和建立 Java 字節碼 的類庫 。性能較 ASM 差,跟 cglib 差很少,可是使用簡單。不少開源框架都在使用它 。工具

主頁:http://www.csg.ci.i.u-tokyo.ac.jp/~ chiba/javassist

Javassist

使用Javassist須要使用javassist.jar性能

優點:
  • 比反射開銷小,性能高。
  • JAVAsist性能高於反射,低於ASM
侷限性:
  • JDK新語法不支持(包括泛型、枚舉),不支持註解修改,但能夠經過底層的javasist類來解決,具體參考:javassist.bytecode.annotaion
  • 不支持數組的初始化,如 String[]{"1","2"},除非只有數組的容量爲1
  • 不支持內部類和匿名類
  • 不支持 continue 和 break 表達式。
  • 對於繼承關係,有些不支持 。例如:- class A{} - class B extends A{} - class C enxends B {}
應用場景:
  • AOP:this

    • 給一個類增長新的方法
    • 給一段語句前面和後面(before/after/around)動態的加代碼
  • Reflection:起到相似反射的效果


javassist 的最外層的 API 和 JAVA 的反射包中的 API 頗爲相似 。spa

它主要由 CtClass , CtMethod, ,以及 CtField 幾個類組成。用以執行和 JDK 反射 API 中 java.lang.Class , java.lang.reflect.Method , java.lang.reflect.Method .Field 相同的 操做 。code

方法操做
  • 修改已有方法的方法體體(插入代碼到已有方法體)
  • 新增方法 刪除方法
  • 佔位符參數介紹:

clipboard.png

示例:blog

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;
/**
 * 建立一個新的類
 * @author Administrator
 *
 */
public class Test10 {
  public static void main(String[] args) throws Exception {
    ClassPool pool = ClassPool.getDefault(); // 類池
    CtClass class1 = pool.makeClass("com.gs.Emp");
    
    //建立屬性
    CtField f1 = CtField.make("private int num;", class1);
    CtField f2 = CtField.make("private String name;", class1);
    class1.addField(f1);
    class1.addField(f2);
    
    //建立方法
    CtMethod setName = CtMethod.make("public void setName(String name){this.name = name;}", class1);
    CtMethod getName = CtMethod.make("public String getName(){return name;}", class1);
    class1.addMethod(setName);
    class1.addMethod(getName);
    
    //添加構造器。  若是是帶參構造器,須要傳遞參數類型,基本數據類型用CtClass獲取,引用類型,須要用pool獲取
    CtConstructor constructor = new CtConstructor(new CtClass[]{CtClass.intType,pool.get("java.lang.String")}, class1);
    constructor.setBody("{this.num = num;this.name = name;}"); //構造器的方法體
    
    class1.writeFile("E:/myjava"); //將上面寫好的類,寫入到這個工做空間中
    
    System.out.println("生成類成功!");
  }
}

執行結果:
生成類成功!繼承

clipboard.png


使用反編譯工具xjad打開:

clipboard.png

相關文章
相關標籤/搜索