Изменить уже загруженный класс с помощью агента Java?

В настоящее время я пытаюсь изменить тела методов, находящихся в классах, уже загруженных JVM. Я знаю, что JVM фактически не позволяет изменять определение уже загруженных классов. Но мои исследования привели меня к таким реализациям, как JRebel или Java Instrumentation API, в обеих из которых используется подход на основе агентов. Я знаю, как это сделать прямо перед загрузкой класса от имени Javassist. Но учитывая, например. JRebel в среде EJB, где определения классов загружаются при запуске приложения, не должна ли модификация байт-кода быть возможной для классов, загруженных JVM?


person pklndnst    schedule 27.04.2015    source источник
comment
Как вы ожидаете, что модификация класса после загрузки будет взаимодействовать с компиляцией JVM?   -  person Patricia Shanahan    schedule 27.04.2015
comment
Вы можете прочитать это: java.dzone.com/articles/reloading-java-classes -401 это интересно.   -  person Michael Laffargue    schedule 27.04.2015
comment
В зависимости от того, что вам нужно, стоит обратить внимание либо на AspectJ (который позволяет добавлять код к существующим объектам), либо на OSGi (который, по сути, является загрузчиком классов на стероидах).   -  person drRobertz    schedule 27.04.2015


Ответы (2)


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

Вы должны отметить, что

  • как показывают ссылки, Instrumentation API является частью стандартного API.
  • однако поддержка переопределения классов необязательна. Вы можете спросить поддерживает ли текущая JVM эту функцию
  • он может быть ограничен поддержкой всех классов; вы можете спросить возможно ли это для определенного класса
  • Even if it is supported, the changes may be limited, to cite the documentation:

    The redefinition may change method bodies, the constant pool and attributes. The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance. These restrictions maybe be lifted in future versions.

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


Таким образом, инструментарий полезен только для отладки, профилирования и т. д.

Но другие фреймворки, такие как контейнеры EJB, предлагающие перезагрузку классов в производственном коде, обычно прибегают к созданию новых ClassLoader, которые создают разные версии классов, которые затем полностью независимы от более старых версий.

В среде выполнения Java идентификатор класса состоит из пары <ClassLoader, Qualified Name>, а не только из полного имени…

person Holger    schedule 27.04.2015
comment
Спасибо, Хольгер. Итак, теперь я знаю, что переопределить класс, изменив тело метода (что полностью удовлетворяет мои потребности), все еще возможно. Таким образом, в документах говорится, что объект Instrumentation может быть получен в качестве параметра при запуске агента Java. Можно ли сохранить ссылку на этот объект и вызвать метод для него позже из моего работающего приложения, когда я хочу переопределить произвольный класс? - person pklndnst; 27.04.2015
comment
Это работает, и для этого шаблона использования нет дополнительных ограничений, вам просто нужно знать, что вы используете функцию, которая может не поддерживаться каждой JVM. В конце этого ответа приведен пример кода приложения, которое (повторно) запускает себя как Java-агент, а уже работает, чтобы получить доступ к Instrumentation API. - person Holger; 27.04.2015

Я не знал, что вы можете использовать инструментальный API для переопределения классов (см. ответ @Holger). Однако, как он отмечает, у этого подхода есть некоторые существенные ограничения. Кроме того, в javadoc говорится:

"Этот метод предназначен для использования в приборах, как описано в спецификации класса."

Использование его для существенного изменения семантики класса... очень плохо с точки зрения системы типов Java.

person Stephen C    schedule 27.04.2015
comment
Это то, чего я ожидал и чего боялся. Спасибо Стивен! - person pklndnst; 27.04.2015