Javaагент. Зачем?

Когда я пытаюсь найти примеры использования Javaagent, в большинстве случаев это примеры работы с байт-кодом. В этих примерах используются сторонние библиотеки, такие как Javaassist.

Насколько я знаю, в Java нет стандартных средств для работы с байт-кодом и в любом случае придется прибегать к библиотекам.

Итак, я попытался использовать эти библиотеки в своем собственном загрузчике классов перед вызовом defineClass(). И, конечно же, это сработало на отлично. Я мог бы изменить байт-код таким же образом, как если бы я сделал это с помощью метода ClassFileTransformer transform().

Правильно ли я понимаю, что есть еще одна полезная функция javaagents, которая, в свою очередь, является их основной функцией? Потому что, во-первых, javaagent дает вам объект Instrumentation, а спецификация Java говорит, что пакет instrument в основном используется для работы с байт-кодом. Но зачем мне это делать, если я просто могу реализовать свой собственный загрузчик классов (то, что я мог сделать задолго до появления пакета instrument)?


person Average Joe    schedule 23.09.2013    source источник


Ответы (3)


Instrumentation API можно использовать во время выполнения, не затрагивая ни код, ни скомпилированный байт-код. Вы можете инструментировать каждую скомпилированную Java-программу (даже не имея кода).

person isnot2bad    schedule 23.09.2013
comment
Не могли бы вы привести пример? - person Average Joe; 23.09.2013
comment
Я смиренно извиняюсь, но все, что они сделали в статье, — это использовалось преобразование байт-кода с помощью ASM. То же самое можно сделать с помощью загрузчика классов - person Average Joe; 23.09.2013
comment
ОК, другой пример: напишите профилировщик, который может подсчитывать количество классов, загруженных/используемых java-приложением. Затем используйте его для профилирования, скажем, веб-сервера Apache Tomcat. Как вы могли бы сделать это, используя собственный загрузчик классов? - person isnot2bad; 23.09.2013
comment
Я вынужден с вами согласиться )) я никак не могу сделать это, используя только свой собственный загрузчик классов - person Average Joe; 23.09.2013

Я думаю, что использование javaagent отличается, потому что оно не является частью вашего приложения. Вы можете написать, например, агент профилирования и использовать его с любым приложением.

person Evgeniy Dorofeev    schedule 23.09.2013
comment
Это довольно разумно. Но насколько я понимаю, Mockito, например, использует javaagent для работы с байт-кодом. Mockito подключает javaagent к JVM. Но если это единственная цель их javaagent, они могут просто использовать свой собственный загрузчик классов. Может я чего-то не понимаю =) - person Average Joe; 23.09.2013
comment
Я думаю, что Mockito создает прокси на лету во время выполнения, как и Spring AOP, хотя это только мое предположение. - person Evgeniy Dorofeev; 23.09.2013

Не путайте Javaagents и Instrumentation. Агент Java может использовать инструменты, но не обязан. Он может использовать все другие функции, предлагаемые платформой Java. Типичным примером агента, не использующего инструменты, является агент JMX. Посмотрите, что предлагают такие инструменты, как JVisualVM. Большинство его функций (за исключением профилировщика) предоставляются через агента JMX без использования инструментов.

Кстати, что касается вашего вопроса о разнице между инструментарием и загрузчиками классов. Пользовательский загрузчик классов не может изменить классы, загруженные через загрузчик классов начальной загрузки, например java.lang.Object (хотя вам следует дважды подумать, прежде чем делать это). Кроме того, ваш пользовательский загрузчик классов должен был реализовать семантику исходных загрузчиков классов для работы. В противном случае, например. если вы попытаетесь перехватить загрузку с помощью делегирования, ваш загрузчик классов пропустит все загруженные классы, когда JVM попытается разрешить зависимости. И все классы, загруженные другим ClassLoader, созданным приложением (например, RMI), не будут обрабатываться вашим пользовательским загрузчиком классов.

Итак, Instrumentation добавляет способ обработки классов независимо от их ClassLoader и (опционально) даже позволяет изменять их по запросу после загрузки.

person Holger    schedule 25.09.2013