使用 javasssist 打印实例变量

Printing instance variable using javasssist

我必须在运行时修改以下 class 以在每个方法结束时打印实例变量 '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++;
    }

}

以下是主要部分 class,我试图在 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

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

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

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