Пример кода проекта в тексте выглядит следующим образом, для дополнительной справки btrace и arthas:
https://github.com/sayhiai/example-javaagent
После версии 5 в jdk есть пакет с именемinstrument
, можно добиться некоторыхочень крутоФункция. Некоторые из рынкаAPM
Инструменты — это усовершенствования, сделанные с их помощью.
Это важный навык для инфраструктуры, но не для развития бизнеса. Многие интервьюеры зададут этот вопрос не потому, что он пригодится в будущем, а потому, что вы правы.jdk
Более знакомый, он хочет убить ваш престиж.
Это нормально, если вы этого не знаете, но если вы говорите, что не знаете, это заходит слишком далеко.
Введение в javaagent
Наша обычная запись в java — этоmain
Метод иjavaagent
Метод входа называетсяpremain
, что указывает на некоторые операции перед основными запусками. javaagent — это пакет jar, который определяет стандартный метод premain() и не требует наследования или реализации каких-либо других классов.
Это условность, и другой причины для этого нет. Этот метод, будь то первая загрузка или каждый раз при загрузке нового ClassLoader, будет выполняться.
Мы можем внести некоторые изменения в байт-код в этом добавленном методе, чтобы добавить функциональность или изменить поведение кода. Этот способ не навязчив, достаточно добавить параметр -javaagent в команду запуска. После Java 6 можно даже динамически устанавливать загрузочный прокси-класс для работающей программы с помощью присоединения.
Опытные студенты обязательно возразят. Фактически, инструмент имеет два основных метода, один из которыхpremain
,одинagentmain
В JVM только один называется; первый - это модификация перед выполненным главным, и последнее контролирует поведение класса во время выполнения. У них все еще есть некоторые различия, потому что АгентМайн опаснее, ограничения будут больше.
Какая польза
получить статистику
Многие продукты apm, такие как Pinpoint, SkyWalking и т. д., используют javaagent для улучшения кода. Информация мониторинга собирается путем динамического добавления статистического кода до и после выполнения метода, функция отслеживания распределенных ссылок может быть реализована за счет совместимости с протоколом OpenTracing. Его принцип аналогичен aop, и в конечном итоге он существует в байт-коде, а снижение производительности зависит от логики вашего кода.
горячее развертывание
Горячая замена кода может быть достигнута с помощью пользовательского ClassLoader. С помощью agentmain будет удобнее реализовать функцию горячего развертывания. После получения Instrumentation через agentmain класс можно динамически переопределить.
диагноз
СотрудничатьJVMTI
технология, можетattach
Перейти к процессу для статистики выполнения и отладки, более популярныйbtrace
иarthas
, нижний слой это технология.
Как сделать
Его условно делят на следующие этапы:
- Создайте пакет Agent JAR для записи улучшенного кода
- Указывает атрибут Premain-Class/Agent-Class в манифесте
- Используйте загрузку параметров или прикрепите для использования
Написать агент
Последним воплощением javaagent является пакет jar. Используйте идею для создания проекта maven по умолчанию.
Создайте обычный класс Java, добавьтеpremain
илиagentmain
методы, их параметры точно такие же.
Напишите Трансформеры
В этой части используется функция дополнительной упаковки jar.
Фактическая логика кода должна быть реализованаClassFileTransformer
интерфейс. Предположим, мы хотим подсчитать время выполнения метода. Мы используемjavaassist
Чтобы улучшить байт-код, это можно сделать с помощью следующего кода.
- Получать
MainRun
Байт-код экземпляра класса - Получать
hello
Экземпляр байт-кода метода - До и после метода добавьте временную статистику, сначала определите переменные
_begin
, а затем написать код напрямую
Не забудьте добавить зависимости maven
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.24.1-GA</version>
</dependency>
Улучшение байт-кода также может использовать другие инструменты, такие как Cglib, asm и т. д.
Файл MANIFEST.MF
Тогда код, который мы пишем, заключается в том, как сообщить об этом публике? ЭтоMANIFEST.MF
документ. Конкретный путь находится в
источник/основной/ресурсы/META-INF/MANIFEST.MF
Manifest-Version: 1.0
premain-class: com.sayhiai.example.javaagent.AgentApp
Обычно упаковка maven перезаписывает этот файл, поэтому нам нужно указать, какой из них необходим.
<build><plugins><plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration></plugin></plugins></build>
Затем в командной строке выполнитеmvn install
Установите в локальный репозиторий или используйтеmvn deploy
Опубликовать на частном сервере.
Прикрепленный список параметров MANIFEST.MF: Премейн-класс Агент-класс Путь загрузочного класса Может-переопределить-классы Can-Retransform-Classs Can-Set-Native-Method-Prefix
использовать
Как использовать, зависит от используемого вами premain или AgentMain.
premain
Вы можете напрямую добавить параметры в командную строку запуска, чтобы включить прокси при запуске jvm.
java -javaagent:agent.jar MainRun
По идее, параметры могут быть привязаны к опциям jvm.
Далее давайте посмотрим на тестовый код.
Это наш класс исполнения. После выполнения выведите hello world напрямую. После улучшения дополнительно выводится время выполнения и некоторая отладочная информация. Среди них отладочная информация выводится до выполнения основного метода.agentmain
Обычно используется в некоторых диагностических инструментах. Используя функции в jdk/lib/tools.jar, вы можете динамически добавлять функции в запущенные программы. В основном это следующие шаги:
- Получите идентификаторы процессов всех jvms, запущенных на машине.
- Выберите JVM для диагностики
- Связать jvm с помощью функции прикрепления
- Используйте функцию loadAgent для загрузки агента и динамического изменения байт-кода.
- удалить JVM
будь осторожен
A, зависит от пакета банок
Как правило, банку пакета агента предусмотрен в виде Fatjar, то есть все зависимости упакованы в большую банку.
Если ваша функция сложна и имеет много зависимостей, то этот пакет jar будет особенно большим.
Поддержание этих зависимостей с помощью отдельных файлов bom — еще один подход. Потребитель сам справляется с проблемой зависимости, но обычно при этом возникают некоторые ошибки, связанные с тем, что пакет jar не может быть найден. Что еще хуже, большинство из них обнаруживаются только во время выполнения.
2. Повторяющиеся имена классов
Не используйте то же имя класса (включая имя пакета), что и в пакетах jdk и tools, иногда вам это сойдет с рук, но вы также попадете в неконтролируемые исключения.
3. Выполняйте ограниченные функции
Как видите, динамическое добавление функциональности в систему довольно круто, но в большинстве случаев очень требовательно к производительности. Вы обнаружите, что некоторые простые диагностические инструменты занимают ваш 1-ядерный процессор, что является обычным делом.
В-четвертых, ClassLoader
Если используемая вами jvm относительно старая и часто генерируется большое количество прокси-классов, это приведет к расширению перманентной области и легко произойдет OOM.
ClassLoader имеет родительский механизм делегирования, если вы хотите заменить соответствующий класс, обязательно выясните, какой загрузчик классов следует использовать. В противном случае замененный класс не вступит в силу.
End
Добавьте свой расширенный код в активную функцию уведомлений, например zk, и вы сможете динамически настраивать поведение приложения, управляя фоном. Если вы интегрируете скриптовый язык, похожий на groovy, теоретически вы можете делать что угодно.
Итак, используйте-javaagent
введен параметрjar
упаковать или использоватьattach
Некоторыми диагностическими средствами, предоставляемыми методом, юная леди не решается воспользоваться им случайно.