Reputation: 103
I am trying to build a very basic Java Hotspot Serviceability agent to dump the bytecode of one specific loaded method. This is the code of my agent :
package sun.jvm.hotspot.jdi;
import sun.jvm.hotspot.oops.InstanceKlass;
import sun.jvm.hotspot.oops.Method;
import sun.jvm.hotspot.oops.Klass;
import sun.jvm.hotspot.memory.SystemDictionary;
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(new SystemDictionary.ClassVisitor() {
public void visit(Klass klass) {
if (klass.getName().asString().equals("MyDebugger")) {
Method method = ((InstanceKlass) klass).findMethod("sendMessage", "()V");
for (byte bc : method.getByteCode()) {
System.out.printf("%02x ", bc);
}
}
}
});
}
public static void main(String[] args) {
new GetBytecode().execute(args);
}
}
which I compile with the following line:
javac --add-modules=jdk.hotspot.agent --add-exports "jdk.hotspot.agent/sun.jvm.hotspot.memory.SystemDictionary=ALL-UNNAMED" --add-exports "jdk.hotspot.agent/sun.jvm.hotspot.memory=ALL-UNNAMED" --add-exports "jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED" --add-exports "jdk.hotspot.agent/sun.jvm.hotspot.tools=ALL-UNNAMED" --add-exports "jdk.hotspot.agent/sun.jvm.hotspot.runtime=ALL-UNNAMED" --add-exports "jdk.hotspot.agent/sun.jvm.hotspot.classfile=ALL-UNNAMED" *.java
It fixes the import issues that I had before, but it seems like since JDK11 the SystemVisitor.ClassVisitor
interface does not exist anymore, as I get an error while compiling :
GetBytecode.java:14: error: cannot find symbol
VM.getVM().getSystemDictionary().allClassesDo(new SystemDictionary.ClassVisitor() {
^
symbol: class ClassVisitor
location: class SystemDictionary
1 error
Also, I cannot find any doc online, which is so frustrating... See javadoc
SystemDictionary in JDK8
SystemDictionary in JDK11
Any fix / workaround is welcome :)
Upvotes: 0
Views: 581
Reputation: 98350
jdk.hotspot.agent
is a JDK internal module, not a part of any standard, not intended for end users, and therefore, not documented.
As a consequence, the API of this module can be arbitrarily changed even in a minor JDK update. The code written for one version of JDK is not required to be compatible with other JDK version. This is quite understood, since Serviceability Agent reflects internal JVM structures, which may change (and do change) from version to version.
So you'd need a different code for JDK 11. It may look like this:
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().sharedDictionary().allEntriesDo((klass, loader) -> {
if (klass.getName().asString().equals("MyDebugger")) {
Method method = ((InstanceKlass) klass).findMethod("sendMessage", "()V");
for (byte bc : method.getByteCode()) {
System.out.printf("%02x ", bc);
}
}
}, null);
}
public static void main(String[] args) {
new GetBytecode().execute(args);
}
}
Upvotes: 2