JAVA.LANG.Intrument Agent Penggunaan
Paket Java.lang.instrument diperkenalkan di JDK5. Pemrogram dapat secara dinamis memodifikasi kode kelas dengan memodifikasi kode bytech dari metode ini. Ini biasanya diproses sebelum metode utama kelas dipanggil, dan diimplementasikan oleh Java untuk menentukan kelas proxy kelas. Sebelum bytecode kelas dimuat ke dalam JVM, metode transformasi ClassFileTransformer akan dipanggil untuk mewujudkan fungsi memodifikasi metode kelas asli dan mengimplementasikan AOP. Keuntungan dari ini adalah bahwa ia tidak akan menghasilkan kelas baru seperti proxy dinamis atau teknologi CGLIB yang mengimplementasikan AOP, dan tidak perlu kelas asli memiliki antarmuka.
(1) Agen adalah pencegat sebelum metode utama Anda, yaitu kode yang mengeksekusi agen sebelum metode utama dijalankan. Kode agen berjalan dalam JVM yang sama dengan metode utama Anda, dimuat oleh ClassLoader sistem yang sama, dan dikelola oleh kebijakan dan konteks keamanan yang sama. Agen nama agak menyesatkan, dan tidak sama dengan agen yang biasanya kita pahami. Agen Java relatif mudah digunakan. Bagaimana cara menulis agen java? Anda hanya perlu mengimplementasikan metode premain: public static void premain (String AgentArgs, Instrumation Inst) Jika definisi premain di atas tidak dapat ditemukan di JDK 6, Anda juga akan mencoba memanggil definisi premain berikut: premain statis public static (string agentArgs)
(2) Kelas agen harus diketik ke dalam paket JAR, dan kemudian meta-inf/mainifest.mf di dalam harus berisi atribut kelas premain. Berikut adalah contoh manifest.mf:
Manifest-Version: 1.0 Kelas premain: myAgent1 dibuat oleh: 1.6.0_06
Kemudian tambahkan manifest.mf ke paket jar Anda. Berikut ini adalah manifes atribut manifes untuk file JAR Agen: kelas premain jika proxy ditentukan ketika JVM dimulai, atribut ini menentukan kelas proxy, yaitu, kelas yang berisi metode premain. Properti ini diperlukan jika proxy ditentukan ketika JVM dimulai. Jika properti tidak ada, JVM akan dibatalkan. Catatan: Properti ini adalah nama kelas, bukan nama file atau jalur. Kelas Agen Jika implementasi mendukung mekanisme untuk memulai agen pada saat tertentu setelah VM dimulai, properti ini menentukan kelas agen. Artinya, kelas yang berisi metode AgentMain. Properti ini diperlukan dan proxy tidak akan dimulai jika tidak ada. Catatan: Ini adalah nama kelas, bukan nama file atau jalur. Boot-Class-Path Mengatur daftar jalur untuk pencarian loader kelas boot. Jalur mewakili direktori atau perpustakaan (biasanya dirujuk sebagai tabung atau perpustakaan zip di banyak platform). Setelah mekanisme spesifik platform untuk menemukan kelas gagal, loader kelas boot mencari jalur ini. Cari jalur dalam urutan yang terdaftar. Jalur dalam daftar dipisahkan oleh satu atau lebih ruang. Jalur menggunakan sintaks komponen jalur dari URI hierarkis. Jika jalur dimulai dengan karakter slash ("/"), itu adalah jalur absolut, jika tidak itu adalah jalur relatif. Jalur relatif diuraikan berdasarkan jalur absolut dari file jar proxy. Abaikan jalur dengan format yang salah dan jalur yang tidak ada. Jika agen dimulai pada saat tertentu setelah VM dimulai, jalur yang tidak mewakili file jar diabaikan. Properti ini opsional. Can-Redefine-Class Boolean (benar atau salah, tidak relevan dengan huruf besar dan kecil). Apakah kelas yang diperlukan untuk proxy ini dapat didefinisikan ulang. Nilai -nilai selain true dianggap salah. Properti ini opsional dan nilai defaultnya salah. Boolean Can-Retransform (benar atau salah, tidak relevan dengan huruf besar dan kecil). Apakah kelas yang diperlukan untuk proxy ini dapat diterjemahkan kembali. Nilai -nilai selain true dianggap salah. Properti ini opsional dan nilai defaultnya salah. Nilai Boolean Method-Method-Prefix CAN-set (benar atau salah, tidak relevan dengan huruf besar dan kecil). Apakah awalan metode asli yang diperlukan oleh proxy ini dapat diatur. Nilai -nilai selain true dianggap salah. Properti ini opsional dan nilai defaultnya salah.
(3) Semua paket guci agen ini akan ditambahkan secara otomatis ke classpath program. Jadi tidak perlu menambahkannya ke classpath secara manual. Kecuali jika Anda ingin menentukan urutan ClassPaths.
(4) Tidak ada batasan jumlah parameter -javaagent dalam program Java, sehingga Anda dapat menambahkan banyak agen Java. Semua agen Java akan dieksekusi dalam urutan yang Anda tentukan. Misalnya:
java -javaagent: myagent1.jar -javaagent: myagent2.jar -jar myprogram.jar
Misalkan fungsi utama dalam myprogram.jar ada di myprogram. Myagent1.jar, myagent2.jar, kelas -kelas yang mengimplementasikan premain dalam dua paket toples ini adalah myagent1, dan urutan eksekusi program myagent2 adalah:
Myagent1.premain -> myagent2.premain -> myprogram.main
(5) Selain itu, ditempatkan premain setelah fungsi utama tidak akan dieksekusi, misalnya:
java -javaagent: myagent1.jar -jar myprogram.jar -javaagent: myagent2.jar
MyAgent2 ditempatkan di belakang myprogram.jar, jadi premain MyAgent2 tidak akan dieksekusi, jadi hasil eksekusi adalah:
Myagent1.premain -> myprogram.main
(6) Setiap agen Java dapat menerima parameter tipe string, yaitu, AgentArgs dalam premain. Agen ini didefinisikan dalam opsi Java. Misalnya:
java -javaagent: myagent2.jar = thisisagentargs -jar myprogram.jar
Nilai AgentArgs yang diterima oleh Premain di MyAgent2 adalah "ThisisagentArgs" (tidak termasuk kutipan ganda).
(7) Instrumentasi dalam parameter: Tambahkan ClassFileTransformer yang ditentukan oleh parameter untuk mengubah file kelas. Transformator khusus di sini mengimplementasikan metode transformasi, yang menyediakan modifikasi pada bytecode kelas yang akan benar -benar dieksekusi, dan bahkan dapat mencapai titik menjalankan metode kelas lain. Misalnya: Tulis Kelas Agen:
Paket org.toy; import java.lang.instrument.instrumentation; impor java.lang.instrument.classfiletransformer; kelas publik perfonagent {private static instrumation inst = null; /** * Metode ini dipanggil sebelum metode utama aplikasi disebut, * Ketika agen ini ditentukan untuk Java VM. **/ public static void premain (String AgentArgs, Instrumentation _inst) {System.out.println ("PerfMonAgent.Premain () dipanggil."); // Inisialisasi variabel statis yang kami gunakan untuk melacak informasi. inst = _inst; // Siapkan transformator file-class. ClassFileTransformer trans = perfMonxformer baru (); System.out.println ("Menambahkan instance perfmonxformer ke JVM."); inst.addtransformer (trans); }}Tulis kelas ClassFiletransformer:
package org.toy;import java.lang.instrument.ClassFileTransformer;import java.lang.instrument.IllegalClassFormatException;import java.security.ProtectionDomain;import javassist.CannotCompileException;import javassist.ClassPool;import javassist.CtBehavior;import javassist.CtClass;import javassist.notfoundException; impor javassist.expr.expreditor; impor javassist.expr.methodcall; kelas publik perfmonxformer mengimplementasikan classfileTransformer {byte publik [] transformasi (classloader loader, string classname, class <?> Classbeingfined, ProtectionDomain domomaindomain, classname, class <?> classbeingredefined, shortomain domeiDomain domaindomain, classname, class <?> classbeingfined, ShiptionDomainromaindomain domomaindomain, classname, class <? IllegalClassformateException {byte [] transformed = null; System.out.println ("Transforming" + ClassName); Classpool pool = classpool.getDefault (); Ctclass cl = null; coba {cl = pool.makeClass (java.io.bytearrayInputStream baru (classFileBuffer)); if (cl.isInterface () == false) {ctbehavior [] Method = cl.getDeclaredBehaviors (); untuk (int i = 0; i <methods.length; i ++) {if (metode [i] .isempty () == false) {domethod (metode [i]); }} transformed = cl.tobytecode (); }} catch (Exception e) {System.err.println ("tidak dapat instrumen" + className + ", pengecualian:" + e.getMessage ()); } akhirnya {if (cl! = null) {cl.detach (); }} return transformed; } private void domethod (metode ctbehavior) melempar notfoundException, tidak dapatCompileException {// method.insertbefore ("long stime = system.nanoTime ();"); // method.insertAfter ("System.out.println (/" leave "+Method.getName ()+" dan waktu:/"+(System.nanoTime ()-stime));"); method.instrument (new expreditor () {public void edit (methodcall m) lemparan cantcompileException {m.replace ("{long stime = System.nanoTime (); $ _ = $ Prosed ($$); System.out.println (/" " +M.getClassName () +". " ":/"+(System.nanoTime ()-STIME));} ");}}); }}); }}Dua kelas di atas adalah inti dari agen. Ketika JVM dimulai, perfmonagent.premain akan dipanggil sebelum aplikasi dimuat. Kemudian, classfiletransforme yang disesuaikan, yaitu perfmonxformer, dipasang di perfmonagent.premain, dan kemudian classfiletransformer kustom dipasang dalam perfmonxformer, dan kemudian contoh perfonxformer ditambahkan ke contoh instrumentasi (ditransmisikan dari JVM). Ini membuat perfmonxformer.transform akan dipanggil ketika kelas dalam aplikasi dimuat. Anda dapat mengubah kelas yang dimuat dalam metode ini. Itu sangat ajaib. Untuk mengubah bytecode kelas, saya menggunakan javassist JBoss. Meskipun Anda tidak harus menggunakannya seperti ini, javassist JBoss sangat kuat, memungkinkan Anda untuk dengan mudah mengubah bytecode kelas.
Dalam metode di atas, saya mengubah bytecode kelas dan menambahkan stime panjang = system.nanoTime (); ke metode masuk metode setiap kelas, dan ditambahkan System.out.println ("MethodClassName.MethodName:"+(System.nanoTime ()-STIME));
Terima kasih telah membaca, saya harap ini dapat membantu Anda. Terima kasih atas dukungan Anda untuk situs ini!