2016-11-27 63 views
0

我必須在運行時修改以下類,以在每個方法的末尾打印實例變量'count'的值。使用javasssist打印實例變量

package test.hib.javaassist; 

import java.io.IOException; 

import javassist.CannotCompileException; 
import javassist.ClassPool; 
import javassist.CtClass; 
import javassist.CtMethod; 
import javassist.NotFoundException; 

public class JavaAssistTest { 

    int count; 


    public void doSomething1(){ 
     count++; 
    } 

    public void doSomething2(){ 
     count++; 
    } 

    public void doSomething3(){ 
     count++; 
    } 

    public void doSomething4(){ 
     count++; 
    } 

} 

以下是主要的類,我試圖通過javaassist的幫助來改變字節碼。

package test.hib.javaassist; 

import java.io.IOException; 

import javassist.CannotCompileException; 
import javassist.ClassPool; 
import javassist.CtClass; 
import javassist.CtMethod; 
import javassist.NotFoundException; 

public class Main { 

    public static void main(String[] args) throws NotFoundException, CannotCompileException, IOException { 

     ClassPool pool = ClassPool.getDefault(); 
     CtClass cc = pool.get("test.hib.javaassist.JavaAssistTest"); 
     CtMethod[] methods = cc.getDeclaredMethods(); 

     for(CtMethod method : methods){ 
      if(! (method.getName().equals("main"))){ 
       method.insertAfter("{System.out.println(count);}"); 
       //method.insertAfter("System.out.println($type);"); 
      } 
     } 

     cc.writeFile(); 

     System.out.println("Completed editting"); 

     JavaAssistTest test = new JavaAssistTest(); 
     test.doSomething1(); 
     test.doSomething2(); 
     test.doSomething3(); 
     test.doSomething4(); 

     System.out.println("Finished"); 

    } 

} 

目前正在打印

Completed editting 
Finished 

我希望它打印

Completed editting 
1 
2 
3 
4 
Finished 

你能pointout在我的代碼錯誤了嗎?

+0

我想像(只是猜測)該類已經加載,所以對.class文件的更改不會反映在當前JVM的運行時。您可以嘗試重新加載班級,例如這裏:http://stackoverflow.com/a/3971771/281108 –

+0

hmm ....看起來很複雜。我嘗試了加載類的不同方式。 \t \t Class testClass = Loader.getSystemClassLoader()。loadClass(「test.hib.javaassist.JavaAssistTest」); \t \t JavaAssistTest test =(JavaAssistTest)testClass.newInstance();但結果沒有變化! – Renjith

+0

我很確定,如果它已經加載,將不會重新加載類。 –

回答

1

Javassist API在這裏有點令人困惑。看看writeFile的執行情況。這是writeFile(".")的快捷方式,它將類保存在程序目錄中,而不是類路徑中。你期望它覆蓋原來的類文件這個方法不會做的。您的系統類加載器將無法找到更新的類文件。

您可以使用writeFile(String)手動將類文件保存在正確的位置,也可以通過調用cc.toClass()強制加載修改後的類,這會在您的類加載器手動查找之前強制加載修改後的類。

+0

謝謝! cc.toClass()工作。最後,我必須在部署在Tomcat Server中的應用程序中使用它。但是它在Java文檔中給出了,它不能應用於在應用程序服務器上運行的應用程序。我必須嘗試使用​​'toClass(java.lang.ClassLoader loader)'。 – Renjith