问题
I am trying to find out if it is possible to get the bytecode of a function after it was loaded to the JVM.
I know I can get the code from the .class
file using ClassLoder and I can manipulate it using Instrumentation, but this is not the issue here.
Suppose I have a compiled Java program called Test.class
and I run, its bytecode will be loaded the JVM, from this point can I get the bytecode?
EDIT: Following the answers I want to point again, my intention is to inspect code which is running on the JVM but I dont have access to its compiled file.
回答1:
Without more context I'm not sure what you're trying to do, but:
If you just want to see the contents of a class file (bytecodes and all), then javap -c Test.class
will spit it out for you.
If you want to see what the code looks like while a JVM is running, an agent might be what you're looking for.
Remember that if your function (method? I'm assuming we're not talking about lambdas here) relies on any variables from the parent scope then the bytecode for said method doesn't describe what it does on its own. Think of inner classes, lambdas, e.t.c.
Edit:
As Peter Lawrey said, if you want to forgo agents, feeding the raw bytes from a class loader into ASM's visitor API is a good start. The ASM doc has a tutorial; Google also turned up this (see part 2). HTH
回答2:
HotSpot Serviceability Agent can do this!
Here is an example how to get the bytecode of remote main(String[])
method in test.HelloWorld
class:
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);
}
}
Run java -cp <JDK_HOME>/lib/sa-jdi.jar:. GetBytecode <PID>
来源:https://stackoverflow.com/questions/32127088/fetching-running-bytecode-from-a-jvm