Как я могу добавить Javaagent к JVM, не останавливая JVM?

Я хочу профилировать приложение Java, не останавливая приложение. Можно ли как-нибудь добавить Javaagent во время работы приложения?

4 ответа

Решение

Это должно быть возможно согласно документации пакета java.lang.instrument.

Запуск агентов после запуска виртуальной машины

Реализация может предоставить механизм для запуска агентов через некоторое время после запуска виртуальной машины. Детали того, как это инициируется, зависят от реализации, но обычно приложение уже запущено, и его основной метод уже был вызван. В случаях, когда реализация поддерживает запуск агентов после запуска виртуальной машины, применяется следующее:

1. Манифест агента JAR должен содержать атрибут Agent-Class. Значением этого атрибута является имя класса агента.
2. Класс агента должен реализовывать открытый статический метод agentmain.
3. Системный загрузчик классов ( ClassLoader.getSystemClassLoader) должен поддерживать механизм добавления файла JAR агента в путь к системному классу.

но я никогда не пробовал:-|

См. Запуск агента Java после запуска программы.

Он ссылается на https://web.archive.org/web/20141014195801/http://dhruba.name/2010/02/07/creation-dynamic-loading-and-instrumentation-with-javaagents/, который в разделе "Динамическая загрузка javaagent во время выполнения" предоставляет рабочий пример:

public static void loadAgent() throws Exception {
    String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();
    String pid = nameOfRunningVM.substring(0, nameOfRunningVM.indexOf('@'));
    VirtualMachine vm = VirtualMachine.attach(pid);
    vm.loadAgent(jarFilePath, "");
    vm.detach();
}

Обратите внимание, что Java 9 требует -Djdk.attach.allowAttachSelf=true присутствовать среди аргументов запуска JVM.

Вы можете использовать ea-agent-loader

При этом загрузка агента во время выполнения будет выглядеть так:

public class HelloAgentWorld
{
    public static class HelloAgent
    {
        public static void agentmain(String agentArgs, Instrumentation inst)
        {
            System.out.println(agentArgs);
            System.out.println("Hi from the agent!");
            System.out.println("I've got instrumentation!: " + inst);
        }
    }

    public static void main(String[] args)
    {
        AgentLoader.loadAgentClass(HelloAgent.class.getName(), "Hello!");
    }
}

Вот библиотека, которая инициализирует aspectj и Spring-аспекты во время выполнения путем внедрения инструментария: https://github.com/subes/invesdwin-instrument

Вы можете использовать его как более сложный образец.

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