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);
    }
}