Выгрузка класса Javaagent

У меня есть java-агент, который обрабатывает байт-код. Я использую API прикрепления в Java 6, чтобы пользователи могли динамически загружать агент и код инструмента и деинструмента с помощью моего агента Java. Я использую атрибут манифеста Boot-Class-Path, чтобы убедиться, что мои классы javagent находятся в пути к классам загрузки, чтобы мои пользователи могли использовать такие классы, как ArrayList и т. д.

Однако проблема связана с версиями. Допустим, пользователь динамически подключает версию 1 моего агента. Затем я дал ему версию 2. Теперь, поскольку его сервер приложений никогда не отключался с тех пор, как он подключил версию 1 моего агента, классы версии 1 все еще загружены.

Мне нужен какой-то способ, чтобы когда моя клиентская версия 2 javaagent выгружалась версии 1.

Я знаю, что одним из способов было бы написать клиентский загрузчик классов для моих классов javaagent и установить для ссылки на загрузчик классов значение null. Однако в этом случае я не смогу инструментировать классы в загрузочном пути к классам, так как мой загрузчик классов будет ниже в иерархии от загрузчика классов загрузки, и поэтому мои пользователи не смогут инструментировать классы, такие как ArrayList, потому что, если я добавлю вызов внутри методов ArrayList к одному из моих методы классов агента, загрузчик классов загрузки не сможет их увидеть.

Итак, есть ли способ решить проблему с загрузочным классом и при этом выгрузить классы предыдущего агента?


person pdeva    schedule 08.08.2009    source источник
comment
Вы можете взглянуть на JavaRebel (zeroturnaround.com/javarebel), который является коммерческим реализация того, что вы пытаетесь сделать. Это может дать вам представление о том, что возможно, а что нет.   -  person skaffman    schedule 12.08.2009


Ответы (4)


Я не эксперт в этой теме, но похоже, что такая выгрузка-замена напрямую не поддерживается.

Но нужно ли выгружать-заменять класс?

Не могли бы вы вместо этого создать никогда не меняющийся класс, с которым общается внешний мир, в котором вы внутренне реализуете систему управления версиями?

Например, вы создаете класс MyToolAgent, который имеет, скажем, статическую строку с именем класса ToolAgentImplementation для использования. При первом выпуске он настроен на использование ToolAgentImplementation1_0. При обновлении до версии 2.0 вы развертываете дополнительный класс с именем ToolAgentImplmenetation2_0 и обновляете класс MyToolAgent для его загрузки и использования. Вы никогда не выгружаете версию 1.0, но перестаете ее использовать. Здесь вы тратите немного памяти, но получаете обновление версии.

Я не знаю, возможно ли это в вашей ситуации, но в целом кажется, что JVM не поддерживает прямую замену в новой версии, но вы должны каким-то образом скрыть это.

person rice    schedule 12.08.2009

Я не уверен, что это сработает, но это может дать вам некоторые варианты...

Вместо того, чтобы пытаться перезагрузить текущий агент (назовем его агентом инструмента), добавьте новый агент (агент установщика). Агент установщика будет иметь ровно 1 функцию: использовать RedefineClasses() для замены исходных классов агента инструмента.

Если вы называете агент установщика номером версии как частью имени класса (MyToolInstallerV1), вы можете продолжать загружать новые установщики, которые обновляют агент инструмента. Если размер становится проблемой, возможно, агент установщика может искать предыдущие установщики и заменять их классы небольшой заглушкой без операций.

person Devon_C_Miller    schedule 13.08.2009

Я еще ничего не инструментировал, но я просто играю с java.util.ServiceLoader и внедрил какую-то архитектуру плагинов с динамической загрузкой-выгрузкой JAR с использованием вашего подхода URLClassLoader.

Я не знаю, что «инструментарий» можно изменить таким образом, но проблемы с версиями и динамической загрузкой-выгрузкой можно отследить, и это действительно быстро проверить, потому что сложные вещи выполняются ServiceLoader (просто следуйте крошечному /META-INF/services/XXX спецификация) и все готово :)

С уважением.

person ATorras    schedule 17.08.2009

Идеальный вариант использования OSGI. Однако не уверен, что вы можете подключить своего агента как пакет.

person Suraj Chandran    schedule 27.01.2011