Java - внедрить Java-агент для запуска JVM

По сути, я пытаюсь написать что-то, в котором перечислены все классы, загруженные JVM. То, что я написал, работает, но работает только на jvm, на котором работает. Я создал java-агент для динамического внедрения в другую JVM, но потом понял, что на самом деле не знаю, как его внедрить. Как мне на самом деле отправить этого агента в другую JVM? Является ли это возможным?

4 ответа

Агенты могут быть введены с помощью HotSpot Attach API.
Запустите следующий фрагмент с $JAVA_HOME/lib/tools.jar на пути класса.

    VirtualMachine vm = VirtualMachine.attach(PID);
    try {
        vm.loadAgent(agentJar);
    } finally {
        vm.detach();
    }

В качестве альтернативы вы можете сделать это с помощью моей утилиты командной строки jattach:

$ jattach PID load instrument false /path/to/agent.jar

Обратите внимание, что для поддержки динамического присоединения ваш Java-агент должен иметь agentmain метод и Agent-Class недвижимость в MANIFEST.MF,

Динамические агенты должны объявить agentmain(String, Instrumentation) метод, который выполняется при подключении в целевой ВМ. Вы можете использовать зависимость tools.jar, которая (до Java 9) включена только в JDK, но не в JRE. Однако вы можете связать свою агентскую программу с JDK и оттуда присоединиться к JVM.

Самым большим недостатком является то, что API отличается для разных виртуальных машин; однако вы можете использовать библиотеку типа byte-buddy-agent, которая содержит различные реализации для разных виртуальных машин. Вложение будет сделано:

ByteBuddyAgent.attach("my.jar", "my-pid");

Это присоединяет агент, содержащийся в my.jar, к процессу Java с идентификатором my-id.

Насколько я понимаю из комментария, вас интересует то, что может проверять удаленную JVM из другого Java-процесса. Если это так, то вам нужен агент обслуживания, а не агент Java.

API агента по удобству обслуживания позволяет подключаться к другому процессу JVM, считывать его память, восстанавливать структуры виртуальных машин и проверять удаленные объекты в режиме отражения.

Вот пример инструмента для перечисления всех классов, загруженных удаленной JVM:

import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.tools.Tool;

public class ListRemoteClasses extends Tool {

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

    @Override
    public void run() {
        VM.getVM().getSystemDictionary().classesDo(klass -> {
            String className = klass.getName().asString().replace('/', '.');
            System.out.println(className);
        });
    }
}

Как запустить это:

java -cp $JAVA_HOME/lib/sa-jdi.jar:. ListRemoteClasses PID

Трудно оказать помощь, не глядя на контент, который вы написали, но это просто для уведомления о том, что существует класс с именем Instrumentation interface (public interface Instrumentation) от java.lang.instrument пакет, предоставляющий сервисы, необходимые для программирования кода языка Java.

Одним из таких методов, предоставляемых этим классом, является getInitiatedClasses который возвращает массив, содержащий все загруженные классы.

Посмотрите документацию здесь

getInitiatedClasses

Class [] getInitiatedClasses (загрузчик ClassLoader)
Возвращает массив всех классов, для которых загрузчик является начальным загрузчиком. Если предоставленный загрузчик имеет значение null, возвращаются классы, инициированные загрузчиком классов начальной загрузки.

Параметры: loader - загрузчик, чей инициированный список классов будет возвращен. Возвращает: массив, содержащий все классы, для которых загрузчик является инициирующим загрузчиком, нулевой длины, если таковых нет.

Другие вопросы по тегам