【问题标题】:Printing instance variable using javasssist使用 javasssist 打印实例变量
【发布时间】:2017-04-11 02:45:37
【问题描述】:

我必须在运行时修改以下类以在每个方法的末尾打印实例变量“count”的值。

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

你能指出我的代码中的错误吗?

【问题讨论】:

  • 我想(只是猜测)该类已经加载,因此对 .class 文件的更改不会反映在当前 JVM 的运行时中。您可以尝试按照描述重新加载类,例如这里:stackoverflow.com/a/3971771/281108
  • 嗯....看起来有点复杂。我尝试了另一种加载课程的方式。类 testClass = Loader.getSystemClassLoader().loadClass("test.hib.javaassist.JavaAssistTest"); JavaAssistTest 测试 = (JavaAssistTest)testClass.newInstance();但结果没有变化!!
  • 我很确定如果已经加载了类,它不会重新加载它。
  • 加载器文档说“与常规类加载器不同,这个类加载器从 ClassPool 获取字节码。”

标签: java javassist


【解决方案1】:

Javassist API 在这里有点混乱。看看writeFile 的实现。它是writeFile(".") 的快捷方式,它将类保存在您的程序目录中,而不是类路径中。您希望它覆盖原始类文件,此方法不会执行此操作。您的系统类加载器将无法找到更新的类文件。

您可以使用writeFile(String) 手动将类文件保存在正确的位置,或者通过调用cc.toClass() 强制加载修改后的类,这会在类加载器手动查找之前强制加载修改后的类。

【讨论】:

  • 谢谢!! cc.toClass() 工作。最后,我必须在 Tomcat Server 中部署的应用程序中使用它。但是在Java doc中给出了同样不能应用于在应用服务器上运行的应用程序。我必须尝试使用​​'toClass(java.lang.ClassLoader loader)'。
猜你喜欢
  • 1970-01-01
  • 2015-02-08
  • 2015-08-01
  • 2017-11-09
  • 1970-01-01
  • 1970-01-01
  • 2022-11-22
  • 2021-04-16
  • 1970-01-01
相关资源
最近更新 更多