Javassist學習筆記(一)

來源:互聯網
上載者:User

一,概述

Javassist是一個動態位元組碼產生架構,包括支援兩種API,Java語言層級和位元組碼層級。其中有些特性是受限的或者不支援的,尤其是JDK1.5裡的部分新特性。

最經常使用的是來提升POJO的能力。

具體技術內容請參考官方文檔

http://www.csg.is.titech.ac.jp/~chiba/javassist/

二,ClassPool
ClassPool 緩衝CtClass的池。體系有些類似java中的ClassLoader,有自己的命名空間。
JVM不允許動態載入類,因此Javassist也提供frozen能力;當然javassist還提供解凍能力。
Javassist還提供修剪pruning的能力,以節省記憶體。如果被修剪,那麼一個類的方法元資訊將不能再被訪問,除了方法名,方法簽名和annotations。一個被prune的類,經過writeFile()或者toBytecode()是不能再被解凍的。因為其元資訊丟失。

在有些情景下,開發人員需要組織自己的ClassPool體繫結構。如果在Tomcat等存在多重ClassLoader的環境中。

ClassPool支援多種添加類路徑的方式,如URL,Inputtream,byte[]等。

其最經典的使用方式

ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("test.Rectangle");
cc.setSuperclass(pool.get("test.Point"));
cc.writeFile();

CtClass可以從ClasPool中脫離,以節省記憶體,通過

cc.detach();

建立ClassPool的方式
ClassPool pool = ClassPool.getDefault(); //便捷方式,維護一個單例
等同於
ClassPool cp = new ClassPool(true);
等同於
ClassPool cp = new ClassPool();
cp.appendSystemPath();

在ClassPool載入類的體系中可以指定Child優先,通過如下代碼:
child.childFirstLookup = true;

Javassist可以更改類名(未凍結)
CtClass.setName("newName");

或者更改已被凍結的類以建立新類

ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("Point");
cc.writeFile();
CtClass cc2 = pool.getAndRename("Point", "Pair");

三,使用ClassLoader

在要修改的類不能事先確定的情況下,不能使用上面的方式更改類,必須配合ClassLoader。當然Javassist也提供了ClassLoader的擴充。
CtClass.toClass();
需要提及的是要選對ClassLoader。例如使用bean對象的載入器

Class c = cc.toClass(bean.getClass().getClassLoader());

載入類時修改
使用javassist.Loader和其事件監聽器機制

修改系統類別
運行時動態重載入類(reload)

4. 內醒和定製Introspection and customization

Javassist 不能刪除方法或者域成員;不能給方法添加參數,必須通過建立新的方法滿足。
Javassist通過內聯的方式給方法添加代碼塊。方法的局部變數名是無法得到的,除非用-g參數編譯類。通過$做首碼來訪問。
insertBefore(), insertAfter(), andaddCatch()

Javassist提供了各種類來協助修改不同類型的資料,其中$在不同的類型中意義有所差別或者Not available.

javassist.expr.MethodCall
javassist.expr.ConstructorCall
javassist.expr.FieldAccess
javassist.expr.NewExpr
javassist.expr.NewArray
javassist.expr.Instanceof
javassist.expr.Cast
javassist.expr.Handler//處理異常

4.3 Adding a new method or field
添加方法時,如果方法之間有依賴調用,如果找不到定義則會失敗。因此需要通過添加抽象方法的方式實現
CtClass cc = ... ;
CtMethod m = CtNewMethod.make("public abstract int m(int i);", cc);
CtMethod n = CtNewMethod.make("public abstract int n(int i);", cc);
cc.addMethod(m);
cc.addMethod(n);
m.setBody("{ return ($1 <= 0) ? 1 : (n($1 - 1) * $1); }");
n.setBody("{ return m($1); }");
cc.setModifiers(cc.getModifiers() & ~Modifier.ABSTRACT);
添加域,應該賦初始值。

注意:Javassist產生的類一般不需要特殊輔助即可運行,但有些特殊情況需要用到一下包
javassist.runtime

4.7限制
enums and generics have not been supported.使用範型時,以普通類型對待。

5. Bytecode level API
位元組碼層級的API提供了更強的能力,包括添加和刪除成員(包括方法)。
6.範型
7. Varargs可變參數
Javassist不支援可變參數,將轉成數組來訪問。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.