??? 關于java字節碼的處理,目前有很多工具,如bcel,asm。不過這些都需要直接跟虛擬機指令打交道。如果你不想了解虛擬機指令,可以采用javassist。javassist是jboss的一個子項目,其主要的優點,在于簡單,而且快速。直接使用java編碼的形式,而不需要了解虛擬機指令,就能動態改變類的結構,或者動態生成類。
??? 下面通過一個簡單的例子,通過javassist來實現如何動態注入代碼。
??? 假設,存在類A,如下:
public class A {
??? public void method() {
??????? for (int i = 0; i < 1000000; i++) {
??????? }
??????? System.out.println("method1");
??? }
}
測試類B如下:
public class B {
??? public static void main(String[] args) {
??????? A a = new A();
??????? a.method();?? ?
??? }
}
現在想統計一下method的執行時間,
默認的實現是修改method:
?public void method() {
??????? long start = System.currentTimeMillis();
??????? for (int i = 0; i < 1000000; i++) {
??????? }
??????? System.out.println("method1");
??????? long end = System.currentTimeMillis();
??????? System.out.println(end - start);
??? }
如果A的方法很多,統計方法的執行時間的代碼就會相應的增加。為了減少工作量,通過動態注入代碼的形式來實現。
修改B的main方法:
??? public static void main(String[] args) throws Exception {
?? ?? //用于取得字節碼類,必須在當前的classpath中,使用全稱
??????? CtClass ctClass = ClassPool.getDefault().get("org.esoft.A");
???????? //需要修改的方法名稱
??????? String mname = "method";?????? ?
??????? CtMethod mold = ctClass.getDeclaredMethod(mname);
???????? //修改原有的方法名稱
??????? String nname = mname + "$impl";
??????? mold.setName(nname);
???????? //創建新的方法,復制原來的方法
??????? CtMethod mnew = CtNewMethod.copy(mold, mname, ctClass, null);
???????? //主要的注入代碼
??????? StringBuffer body = new StringBuffer();
??????? body.append("{\nlong start = System.currentTimeMillis();\n");
??????? //調用原有代碼,類似于method();($$)表示所有的參數
??????? body.append(nname + "($$);\n");
??????? body.append("System.out.println(\"Call to method "
??????????????????? + mname
??????????????????? + " took \" +\n (System.currentTimeMillis()-start) + "
??????????????????? + "\" ms.\");\n");
????? ?
??????? body.append("}");
???????? //替換新方法
??????? mnew.setBody(body.toString());
???????? //增加新方法
??????? ctClass.addMethod(mnew);
??????? //類已經更改,注意不能使用A a=new A();,因為在同一個classloader中,不允許裝載同一個類兩次
??????? A a=(A)ctClass.toClass().newInstance();
??????? a.method();
??? }
這只是簡單的一個應用。javassist還提供了很多的功能,用于更改類結構。有興趣的可以參考相關文檔
posted on 2007-02-10 21:02
布衣郎 閱讀(13765)
評論(9) 編輯 收藏 所屬分類:
jdk相關