Java Hotspot Serviceability Agent SystemDictionary.ClassVisitor 自 JDK11 后不可用
Java Hotspot Serviceability Agent SystemDictionary.ClassVisitor unavailable since JDK11
我正在尝试构建一个非常基本的 Java 热点可服务性代理来转储一个特定加载方法的字节码。这是我代理的代码:
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);
}
}
我用以下行编译:
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
它修复了我之前遇到的导入问题,但似乎自 JDK11 以来,SystemVisitor.ClassVisitor
接口不再存在,因为我在编译时遇到错误:
GetBytecode.java:14: error: cannot find symbol
VM.getVM().getSystemDictionary().allClassesDo(new SystemDictionary.ClassVisitor() {
^
symbol: class ClassVisitor
location: class SystemDictionary
1 error
另外,我在网上找不到任何文档,这真是令人沮丧... See javadoc
SystemDictionary in JDK8
SystemDictionary in JDK11
欢迎任何修复/解决方法:)
jdk.hotspot.agent
是一个 JDK 内部模块,不是任何标准的一部分,不适合最终用户,因此没有记录。
因此,此模块的 API 即使在较小的 JDK 更新中也可以任意更改。为 JDK 的一个版本编写的代码不需要与其他 JDK 版本兼容。这是很容易理解的,因为 Serviceability Agent 反映了内部 JVM 结构,它可能会随着版本的不同而改变(并且确实会改变)。
所以您需要为 JDK 11 使用不同的代码。它可能看起来像这样:
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);
}
}
我正在尝试构建一个非常基本的 Java 热点可服务性代理来转储一个特定加载方法的字节码。这是我代理的代码:
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);
}
}
我用以下行编译:
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
它修复了我之前遇到的导入问题,但似乎自 JDK11 以来,SystemVisitor.ClassVisitor
接口不再存在,因为我在编译时遇到错误:
GetBytecode.java:14: error: cannot find symbol
VM.getVM().getSystemDictionary().allClassesDo(new SystemDictionary.ClassVisitor() {
^
symbol: class ClassVisitor
location: class SystemDictionary
1 error
另外,我在网上找不到任何文档,这真是令人沮丧... See javadoc
SystemDictionary in JDK8
SystemDictionary in JDK11
欢迎任何修复/解决方法:)
jdk.hotspot.agent
是一个 JDK 内部模块,不是任何标准的一部分,不适合最终用户,因此没有记录。
因此,此模块的 API 即使在较小的 JDK 更新中也可以任意更改。为 JDK 的一个版本编写的代码不需要与其他 JDK 版本兼容。这是很容易理解的,因为 Serviceability Agent 反映了内部 JVM 结构,它可能会随着版本的不同而改变(并且确实会改变)。
所以您需要为 JDK 11 使用不同的代码。它可能看起来像这样:
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);
}
}