You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JDK11+环境下Java Hotspot SA的SystemDictionary.ClassVisitor不可用求解

修复方案

问题根因

JDK9模块化重构后,原SystemDictionary内部定义的ClassVisitor接口被迁移至sun.jvm.hotspot.utilities.ClassVisitor独立接口,allClassesDo方法入参同步修改为新接口类型,导致适配JDK8的代码在JDK11+环境编译时找不到内部类符号。

代码修改

导入新的ClassVisitor接口,调整实例化逻辑,修改后完整代码如下:

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;
import sun.jvm.hotspot.utilities.ClassVisitor;

public class GetBytecode extends Tool {

    @Override
    public void run() {
        VM.getVM().getSystemDictionary().allClassesDo(new 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);
    }
}

编译命令调整

新增utilities包的导出声明,完整编译命令如下:

javac --add-modules=jdk.hotspot.agent \
--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" \
--add-exports "jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED" \
*.java

跨版本兼容替代实现

如果需要代码同时兼容JDK8、JDK11+环境,可以直接通过堆遍历获取所有已加载类,避开allClassesDo的接口差异:

@Override
public void run() {
    VM.getVM().getObjectHeap().iterate(heapObject -> {
        if (!(heapObject instanceof InstanceKlass)) {
            return;
        }
        InstanceKlass klass = (InstanceKlass) heapObject;
        if (!klass.getName().asString().equals("MyDebugger")) {
            return;
        }
        Method method = klass.findMethod("sendMessage", "()V");
        if (method == null) {
            return;
        }
        for (byte bc : method.getByteCode()) {
            System.out.printf("%02x ", bc);
        }
    });
}

运行注意事项

  • 运行SA工具的JDK版本必须和目标Java进程的JDK版本完全一致,否则会触发版本校验错误
  • 运行时同样需要携带上述--add-modules和--add-exports参数,否则会出现运行时权限错误

内容的提问来源于stack exchange,提问作者AntoineG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 03:15:02