java.lang.instrument Agent Использование
Пакет java.lang.instrument был введен в JDK5. Программисты могут динамически изменять код класса, изменяя байт -код метода. Обычно это предварительно обработано до того, как будет вызван основной метод класса, и реализуется Java для указания класса прокси в классе. До того, как байт -код класса загружен в JVM, метод преобразования ClassFileTransformer будет вызван для реализации функции изменения исходного метода класса и реализации AOP. Преимущество этого заключается в том, что он не будет производить новый класс, такой как динамический прокси или технология CGLIB, которая реализует AOP, и у оригинального класса нет необходимости иметь интерфейс.
(1) Агент является перехватчиком перед вашим основным методом, то есть кодом, который выполняет агент до выполнения основного метода. Код агента работает в том же JVM, что и ваш основной метод, загружается одним и тем же системным классом и управляется той же политикой безопасности и контекстом. Имя агента немного вводит в заблуждение, и он не совсем такой же, как агент, которого мы обычно понимаем. Агент Java относительно прост в использовании. Как написать агента Java? Вам нужно только реализовать метод Premain: Public Static void Premain (String Agentargs, Instrumentation Inst), если вышеупомянутое определение Premain не может быть найдено в JDK 6, вы также попытаетесь вызвать следующее определение Premain: Public Static Void Premain (String Agentargs)
(2) Класс агента должен быть введен в пакет JAR, а затем мета-инф/mainifest.mf внутри должен содержать атрибут класса Premain. Вот пример Manifest.mf:
Manifest-Version: 1.0 Premain-Class: MyAgent1 Создан: 1.6.0_06
Затем добавьте manifest.mf в свой пакет JAR. Ниже приведены манифестные атрибуты для файла JAR агента: Premain-Class Если прокси указывается, когда JVM запускается, этот атрибут указывает класс прокси, то есть класс, содержащий метод Premain. Это свойство требуется, если прокси указывается при запуске JVM. Если собственности не существует, JVM прервет. Примечание. Это свойство является именем класса, а не именем файла или пути. Класс агента Если реализация поддерживает механизм для запуска агента в определенный момент после начала виртуальной машины, это свойство определяет класс агента. То есть класс, содержащий метод агента. Это свойство требуется, и прокси не будет запущен, если его не существует. Примечание: это имя класса, а не имя файла или путь. Boot-Class-Path Устанавливает список путей для поиска загрузки класса загрузки. Пути представляют каталоги или библиотеки (обычно называемые JAR или ZIP библиотеки на многих платформах). После того, как механизм поиска класса не сбои, загруженного загрузчика ищет эти пути. Поиск по пути в перечисленном заказе. Пути в списке разделены одним или несколькими пространствами. Пути используют синтаксис компонента пути иерархического URI. Если путь начинается с символа Slash ("/"), это абсолютный путь, в противном случае это относительный путь. Относительный путь анализируется на основе абсолютного пути прокси -файла JAR. Игнорировать пути с неправильным форматом и несуществующими путями. Если агент запускается в определенный момент после запуска виртуальной машины, путь, который не представляет файл JAR, игнорируется. Это свойство необязательно. Can-Redefine Class Boolean (истинная или ложная, не относящаяся к верхнему и нижнему региону). Можно ли переопределить необходимые классы для этого прокси. Значения, отличные от истины, считаются ложными. Это свойство необязательно, а значение по умолчанию неверно. Can-Retransform-Class Boolean (истинная или ложная, не относящаяся к верхнему и нижнему корпусу). Можно ли изменить необходимые классы для этого прокси. Значения, отличные от истины, считаются ложными. Это свойство необязательно, а значение по умолчанию неверно. Can-Set-Con-Method-Prefix Boolean Значение (TRUE или FALSE, не относящаяся к верхнему и нижнему случаю). Может ли быть установлен пристальный префикс метода, требуемый этим прокси. Значения, отличные от истины, считаются ложными. Это свойство необязательно, а значение по умолчанию неверно.
(3) Все эти пакеты JAR -агента будут автоматически добавлены в группу программы. Таким образом, нет необходимости добавлять их в городскую дорожку вручную. Если вы не хотите указать порядок путей.
(4) Нет ограничения на количество параметров -джаваагента в программе Java, так что вы можете добавить столько же агентов Java. Все агенты Java будут выполнены в определении, который вы определяете. Например:
java -Javaagent: myagent1.jar -javaagent: myagent2.jar -jar myprogram.jar
Предположим, что основная функция в myprogram.jar находится в MyProgram. Myagent1.jar, myagent2.jar, классы, которые реализуют Premain в этих двух пакетах JAR MyAgent1, а порядок выполнения программы Myagent2 будет:
Myagent1.premain -> myagent2.premain -> myprogram.main
(5) Кроме того, Premain, установленная после того, как основная функция не будет выполнена, например:
java -Javaagent: myagent1.jar -jar myprogram.jar -javaagent: myagent2.jar
MyAgent2 находится за myProgram.jar, поэтому Premain of MyAgent2 не будет выполнена, поэтому результат выполнения будет:
Myagent1.premain -> myprogram.main
(6) Каждый агент Java может получить параметр строкового типа, то есть агенты в Premain. Этот агент определяется в варианте Java. Например:
java -Javaagent: myagent2.jar = thisisagentargs -jar myprogram.jar
Стоимость агентов, полученных Premain в Myagent2, будет «Thisisagentargs» (исключая двойные цитаты).
(7) Инструментарий в параметре: добавьте ClassFileTransformer, определенный параметром для изменения файла класса. Пользовательский трансформатор здесь реализует метод преобразования, который обеспечивает модификацию на байт -код класса, который будет фактически выполнять, и даже может достичь точки выполнения другого метода класса. Например: написать класс агента:
пакет org.toy; импорт java.lang.instrument.instrumentation; импорт java.lang.instrument.classfileTransformer; Public Class Perfmonagent {Private Static Instatication Inst = null; /** * Этот метод вызывается до того, как главный метод приложения вызывается, * Когда этот агент указан в виртуальной машине Java. **/ public static void premain (String Agentargs, Instrumentation _inst) {System.out.println ("perfmonagent.premain () был вызван."); // Инициализировать статические переменные, которые мы используем для отслеживания информации. inst = _inst; // Установите трансформатор класса. ClassFileTransformer Trans = new PerfmonxFormer (); System.out.println («Добавление экземпляра Perfmonxformer в JVM.»); inst.addtransformer (trans); }}Напишите класс ClassFileTransformer:
пакет org.toy; импорт java.lang.instrument.classfiletransformer; импорт java.lang.instrument.illegalclassformatexception; импорт java.security.protectiondomad; импорт javassist.cannotcompilexception; импорт javassist.classpool; import.comvisior; climpassior; climpassior; climbassior; javassist.notfoundexception; import javassist.expr.expreditor; import javassist.expr.methodcall; открытый класс Perfmonxformer реализует ClassFileTransformer {public Byte [] Transform (ClassLoader Loader, Classfile, класс <?> ClassbeingfectedEffice, Ferationdersemonderdy, byte [] classfureBuffer). байт [] преобразован = null; System.out.println («Преобразование» + Classname); ClassPool Pool = classPool.getDefault (); Ctclass cl = null; try {cl = pool.makeclass (new java.io.bytearrayinputstream (classfilebuffer)); if (cl.isinterface () == false) {ctbehavior [] methods = cl.getDeclaredBehaviors (); for (int i = 0; i <methods.length; i ++) {if (methods [i] .isempty () == false) {domethod (methods [i]); }} transformed = cl.tobytecode (); }} catch (Exception e) {System.err.println ("Не удается инструмент" + classname + ", исключение:" + e.getmessage ()); } наконец {if (cl! = null) {cl.detach (); }} вернуть преобразован; } private void domethod (метод ctbehavior) бросает notfoundexception, невозможным concompileexception {// method.insertbefore ("long stime = system.nanotime ();"); // method.insertafter ("System.out.println (/" Off "+method.getName ()+" и Time:/"+(System.Nanotime ()-Stime));"); method.instrument (new expreditor () {public void edit (methodcall m) throws не concompileexception {m.replace ("{long stime = system.nanotime (); $ _ = $ езда ($$); System.out.println (/" " +m.getClassname () +". ":/"+(System.nanotime ()-Stime));} ");}}); }}); }}Вышеуказанные два класса являются ядром агента. Когда JVM начинается, Perfmonagent.premain будет вызван до загрузки приложения. Затем индивидуальный ClassFileTransforme, а именно Perfmonxformer, создан в perfmonagent.premain, а затем пользовательский ClassFileTransformer создается в PerfmonXformer, а затем в экземпляр PerfmonxFormer добавляется экземпляр инструмента (передается из JVM). Это делает perfmonxformer.transform, когда класс в приложении загружается. Вы можете изменить загруженный класс в этом методе. Это действительно волшебно. Чтобы изменить байт -код класса, я использовал Jboss 'Javassist. Хотя вам не нужно использовать его так, Jboss 'Javassist действительно мощный, что позволяет вам легко изменить байт -код класса.
В приведенном выше методе я изменил байт -код класса и добавил Long Stime = System.nanotime (); к входу метода каждого класса и добавленной system.out.println ("methodclassname.methodname:"+(System.nanotime ()-Stime));
Спасибо за чтение, я надеюсь, что это поможет вам. Спасибо за поддержку этого сайта!