2016-08-15 5 views
5

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

ответ

-1

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

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

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

getInitiatedClasses

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

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

+0

Я знаю об этом. Проблема в том, что jar уже запущен, и мне нужно получить javaagent для подключения к нему. – Stoud

3

Агенты могут быть введены 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.

+0

У меня небольшая проблема с агентами. Я предполагаю, что наиболее стандартная практика заключается в том, чтобы упаковать ваш контрольный агент отдельно от вашей целевой JVM. Когда вызывается мой 'agentmain()', я пытался найти JVM-класс, вызывая 'Class.forName (« pkg.name »)', но он всегда возвращает 'NoClassDefFoundError'. Я разместил здесь вопрос (https://stackoverflow.com/questions/46523055/using-class-forname-in-java-instrumentation-agent?noredirect1_comment80003396_46523055)~here]. Я немного смущен, почему агент, даже когда он подключен к виртуальной машине, не может ссылаться на свои классы. – ha9u63ar

6

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

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

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

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

+0

Будет ли pid таким же, как показано в списке задач? – Stoud

+0

Да. Идентификатор процесса ОС. –

+0

Я попытался это сделать, и при тестировании я обнаружил, что мой метод agentmain никогда не вызывается. – Stoud

3

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

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

Вот инструмент выборки, чтобы перечислить все классы, загруженные удаленной 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 

 Смежные вопросы

  • Нет связанных вопросов^_^