2016-11-27 64 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