我试图找出在将函数加载到JVM之后是否可以获取函数的字节码。
我知道我可以使用ClassLoder从.class
文件中获取代码,我可以使用Instrumentation来操作它,但这不是问题所在。
假设我有一个名为Test.class
的编译Java程序并且我运行,它的字节码将被加载到JVM中,从这一点我可以得到字节码吗?
编辑: 根据我想再次指出的答案,我的目的是检查在JVM上运行的代码,但我无权访问其编译文件。
答案 0 :(得分:1)
如果没有更多的背景,我不确定你要做什么,但是:
如果您只是想查看类文件(字节码和所有内容)的内容,那么javap -c Test.class
会为您吐出来。
如果您想在JVM运行时看到代码的样子,agent可能就是您要找的。 p>
请记住,如果你的函数(方法?我假设我们在这里不讨论lambdas)依赖于父作用域中的任何变量,那么所述方法的字节码就不能描述它自己的作用。想想内部类,lambdas,e.t.c。
修改强>
正如Peter Lawrey所说,如果你想放弃代理,将类加载器中的原始字节提供给ASM的访问者API是一个好的开始。 ASM doc有一个教程;谷歌也出现了this(见第2部分)。 HTH
答案 1 :(得分:1)
HotSpot Serviceability Agent可以做到这一点!
以下是如何在main(String[])
类中获取远程test.HelloWorld
方法的字节码的示例:
import sun.jvm.hotspot.oops.InstanceKlass;
import sun.jvm.hotspot.oops.Method;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.tools.Tool;
public class GetBytecode extends Tool {
@Override
public void run() {
VM.getVM().getSystemDictionary().allClassesDo(klass -> {
if (klass.getName().asString().equals("test/HelloWorld")) {
Method method = ((InstanceKlass) klass).findMethod("main", "([Ljava/lang/String;)V");
for (byte bc : method.getByteCode()) {
System.out.printf("%02x ", bc);
}
}
});
}
public static void main(String[] args) {
new GetBytecode().execute(args);
}
}
运行java -cp <JDK_HOME>/lib/sa-jdi.jar:. GetBytecode <PID>