如何查看Java Agent修改后实际执行的类源码?
查看Java Agent修改后的类源码的实用方法
你遇到的情况太典型了——Java Agent在运行时动态修改了类的字节码,但IDE默认只会加载你写的原始.java/.class文件,自然看不到实际执行的修改后代码。下面给你几个靠谱的解决办法,结合你的Javassist Agent示例来说明:
方法1:在Agent中直接保存修改后的字节码到本地
既然你用了Javassist来修改类,那可以在生成修改后的字节码后,把它写到磁盘上,之后用反编译工具查看。
修改你的RuntimeTimerTransformer类里的transformClass方法,在b = cl.toBytecode();之后添加这段代码:
// 保存修改后的字节码到本地文件,方便后续反编译查看 try (FileOutputStream fos = new FileOutputStream("modified-" + cl.getSimpleName() + ".class")) { fos.write(b); System.out.println("已保存修改后的类文件: modified-" + cl.getSimpleName() + ".class"); } catch (IOException e) { e.printStackTrace(); }
运行程序后,你就能在项目根目录找到modified-App.class文件,直接用IntelliJ打开它(IDE会自动反编译),就能看到Agent修改后的完整代码逻辑。
方法2:用IntelliJ IDEA的调试功能查看已加载类的字节码
在调试状态下,IntelliJ可以直接查看JVM中当前加载的类的实际字节码,步骤如下:
- 给你的
Main.java里的app.execute("John");行打个断点,启动调试 - 当程序停在断点时,打开Debug工具窗口,找到当前线程的调用栈,右键点击
App.execute方法,选择Show Bytecode - 如果你想看到更接近源码的反编译结果,可以安装像Bytecode Viewer这样的插件,或者把字节码复制到JD-GUI等反编译工具中。
方法3:用Java自带工具导出已加载的修改后类
用jps命令找到你的Java进程ID,然后用jcmd工具导出指定类:
# 导出修改后的App类到文件 jcmd <你的进程ID> dump_class app.App modified-App.class
导出后同样用反编译工具打开查看即可。
结合你的示例,修改后的execute方法逻辑其实是这样的:
从你的输出日志能反推出来,Agent给execute方法做了这些改动:
public void execute(String param) { long $_start = System.nanoTime(); System.out.println(this); // 对应输出里的app.app.App@3e6fa38a param = "Robert"; // 把传入的John改成了Robert // 你原本的代码逻辑 String message = "Hello World"; System.out.println(message + " " + param); // Agent插入的结尾代码 long $_end = System.nanoTime(); long $_total = $_end - $_start; System.out.println($_total); // 输出耗时736583 throw new RuntimeException("Break!"); // 抛出异常终止程序 }
内容的提问来源于stack exchange,提问作者Yan Khonski
相关产品推荐
相关产品推荐

