Системный справочник агента работоспособности точки доступа Java.ClassVisitor недоступен с JDK11

#java #jvm-hotspot

Вопрос:

Я пытаюсь создать очень простой агент обслуживания точки доступа 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("x ", 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
 

Кроме того, я не могу найти ни одного документа в Интернете, что так расстраивает… См. javadoc

SystemDictionary в JDK8
SystemDictionary в JDK11

Любое исправление / обходной путь приветствуется 🙂

Ответ №1:

jdk.hotspot.agent это внутренний модуль JDK, не являющийся частью какого-либо стандарта, не предназначенный для конечных пользователей и, следовательно, не документированный.

Как следствие, API этого модуля может быть произвольно изменен даже при незначительном обновлении JDK. Код, написанный для одной версии JDK, не обязательно должен быть совместим с другой версией JDK. Это вполне понятно, поскольку Агент работоспособности отражает внутренние структуры 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("x ", bc);
                }
            }
        }, null);
    }

    public static void main(String[] args) {
        new GetBytecode().execute(args);
    }
}