Cara menggunakan Agen Java
Pengenalan kepada teknologi Java Agent
Java Agent diterjemahkan secara literal sebagai ejen Java, dan juga sering dipanggil teknologi probe Java.
Java Agent, teknologi yang diperkenalkan dalam JDK1.5, boleh mengubah suai kod bait Java secara dinamik pada masa jalan. Kelas dalam Java disusun untuk membentuk kod bait yang dilaksanakan oleh JVM JVM memperoleh maklumat kod bait ini sebelum melaksanakan kod bait ini, dan mengubah kod bait ini melalui penukar kod bait untuk menyelesaikan beberapa ciri tambahan.
Java Agent ialah pakej jar yang tidak boleh dijalankan secara bebas Ia berfungsi melalui proses JVM yang dilampirkan pada program sasaran. Apabila bermula, anda hanya perlu menambah parameter -javaagent pada parameter permulaan program sasaran untuk menambah ClassFileTransformer
penukar kod bait, yang bersamaan dengan menambah pemintas sebelum kaedah utama.
Pengenalan fungsi Java Agent
Java Agent terutamanya mempunyai fungsi berikut:
Java Agent
Dapat memuatkan bait Java Memintas dan mengubah suai kod bait sebelum kod;Ejen Java boleh mengubah suai kod bait yang dimuatkan semasa Jvm berjalan;
Senario aplikasi Java Ejen:
Fungsi penyahpepijatan IDE, seperti Eclipse, IntelliJ IDEA; >Pelbagai alat analisis prestasi, seperti Visual VM, JConsole, dsb.;
Prinsip pelaksanaan Agen Java-
Sebelum memahami prinsip pelaksanaan
, anda perlu mempunyai pemahaman yang jelas tentang mekanisme pemuatan kelas Java. Satu adalah untuk melaksanakan melalui prautama sebelum kaedah lelaki dilaksanakan yang lain adalah untuk mengubah suai program semasa ia sedang berjalan, yang perlu dilaksanakan melalui Attach dalam JVM Prinsip pelaksanaan Attach adalah berdasarkan JVMTI. - Terutamanya memintas dan mengubah suai bytecode sebelum kelas dimuatkan Mari kita perkenalkan istilah utama ini masing-masing:
-
JVMTI
ialah , iaitu koleksi antara muka yang didedahkan oleh JVM untuk sambungan pengguna JVMTI didorong oleh peristiwa Setiap kali JVM melaksanakan logik tertentu, ia akan mencetuskan beberapa antara muka panggilan balik ini, pengguna boleh meluaskan diri mereka
JVMTI ialah asas bersatu untuk melaksanakan Debugger, Profiler, Monitor, Penganalisis Benang dan alatan lain, dan dilaksanakan dalam mesin maya Java arus perdanaJava Agent
JVMTIAgent ialah perpustakaan dinamik yang menggunakan beberapa antara muka yang didedahkan oleh JVMTI untuk melakukan perkara yang kita mahu lakukan tetapi tidak boleh lakukan dalam keadaan biasa, tetapi untuk serasi dengan perpustakaan Dinamik biasa untuk membezakan, ia biasanya melaksanakan satu atau lebih fungsi berikut:
JVM Tool Interface
fungsi, jika ejen dimulakan Dimuatkan, melalui tetapan parameter JVM
akan dipanggil semasa proses pemuatan, dan
- javaagent
bergantung pada JVMTIAgent instrumen (pustaka dinamik yang sepadan di bawah Linux ialah libinstrument.so), dan terdapat juga pemalam yang dipanggil
Agent_OnLoad
(Java Programming Language Instrumentation Services Agent), yang khusus ditulis untuk bahasa Java. -
yang disokong oleh perkhidmatan stub melaksanakan dua kaedah Agent_OnLoad dan Agent_OnAttach, yang bermaksud bahawa apabila digunakan, ejen boleh dimuatkan pada permulaan atau pada permulaan dimuatkan secara dinamik pada masa jalan. Pemuatan semasa permulaan juga boleh digunakan untuk memuatkanAgent_OnAttach
instrumen secara tidak langsung melalui kaedah yang serupa dengan laluan pakej -javaagent:jar Pemuatan dinamik pada masa jalan bergantung pada mekanisme lampiran JVM Ejen -
JVM AttachAgent_OnUnload
merujuk kepada fungsi komunikasi antara proses yang disediakan oleh JVM, yang membenarkan satu proses menghantar arahan kepada proses lain dan melakukan beberapa operasi dalaman, seperti pembuangan benang, kemudian Anda perlu melaksanakan jstack, dan kemudian hantar pid dan parameter lain ke utas yang perlu dibuang untuk pelaksanaan -
Kes Agen Java
untuk mencapai ini.JPLISAgent
Mari ambil masa pelaksanaan kaedah cetakan sebagai contoh Gunakan - Mula-mula kita perlu membina projek
yang diperkemas, di mana kita membina dua subprojek Maven, satu untuk melaksanakan Ejen pemalam dan satu untuk melaksanakan program sasaran ujian.
instrument agent
- Kami mengimport pakej yang kedua-dua projek mempunyai kebergantungan biasa dalam aplikasi induk
Mula-mula kami membina program Sasaran ujian<dependencies> <dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.28.0-GA</version> </dependency> </dependencies>
Salin selepas log masuk
- akan dipanggil apabila ejen dipunggah
// 启动类 public class APPMain { public static void main(String[] args) { System.out.println("APP 启动!!!"); AppInit.init(); } } // 模拟的应用初始化的类 public class AppInit { public static void init() { try { System.out.println("APP初始化中..."); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }
然后我们启动程序,测试是否能正常执行,程序正常执行之后,我们开始构建探针程序
探针程序中我们需要编写,改变原有class的Transformer
,通过自定义的Transformer类完成输出方法执行时间的功能,
首先构检Agent程序的入口
public class RunTimeAgent { public static void premain(String arg, Instrumentation instrumentation) { System.out.println("探针启动!!!"); System.out.println("探针传入参数:" + arg); instrumentation.addTransformer(new RunTimeTransformer()); } }
这里每个类加载的时候都会走这个方法,我们可以通过className进行指定类的拦截,然后借助javassist这个工具,进行对Class的处理,这里的思想和反射类似,但是要比反射功能更加强大,可以动态修改字节码。
javassist是一个开源的分析、编辑和创建Java字节码的类库。
import javassist.ClassPool; import javassist.CtClass; import javassist.CtMethod; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.security.ProtectionDomain; public class RunTimeTransformer implements ClassFileTransformer { private static final String INJECTED_CLASS = "com.zhj.test.init.AppInit"; @Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { String realClassName = className.replace("/", "."); if (realClassName.equals(INJECTED_CLASS)) { System.out.println("拦截到的类名:" + realClassName); CtClass ctClass; try { // 使用javassist,获取字节码类 ClassPool classPool = ClassPool.getDefault(); ctClass = classPool.get(realClassName); // 得到该类所有的方法实例,也可选择方法,进行增强 CtMethod[] declaredMethods = ctClass.getDeclaredMethods(); for (CtMethod method : declaredMethods) { System.out.println(method.getName() + "方法被拦截"); method.addLocalVariable("time", CtClass.longType); method.insertBefore("System.out.println(\"---开始执行---\");"); method.insertBefore("time = System.currentTimeMillis();"); method.insertAfter("System.out.println(\"---结束执行---\");"); method.insertAfter("System.out.println(\"运行耗时: \" + (System.currentTimeMillis() - time));"); } return ctClass.toBytecode(); } catch (Throwable e) { //这里要用Throwable,不要用Exception System.out.println(e.getMessage()); e.printStackTrace(); } } return classfileBuffer; } }
我们需要在Maven中配置,编译打包的插件,这样我们就可以很轻松的借助Maven生成Agent的jar包
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <!-- 指定maven编译的jdk版本。若不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 --> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.2.0</version> <configuration> <archive> <!--自动添加META-INF/MANIFEST.MF --> <manifest> <addClasspath>true</addClasspath> </manifest> <manifestEntries> <Menifest-Version>1.0</Menifest-Version> <Premain-Class>com.zhj.agent.RunTimeAgent</Premain-Class> <Can-Redefine-Classes>true</Can-Redefine-Classes> <Can-Retransform-Classes>true</Can-Retransform-Classes> </manifestEntries> </archive> </configuration> </plugin> </plugins> </build>
否则我们需要在resources下创建META-INF/MANIFEST.MF文件,文件内容如下,我们可以看出这个与Maven中的配置是一致的,然后通过配置编译器,借助编译器打包成jar包,需指定该文件
Manifest-Version: 1.0 Premain-Class: com.zhj.agent.RunTimeAgent Can-Redefine-Classes: true Can-Retransform-Classes: true
告示文件MANIFEST.MF参数说明:
Manifest-Version
文件版本
Premain-Class
包含 premain 方法的类(类的全路径名)main方法运行前代理
Agent-Class
包含 agentmain 方法的类(类的全路径名)main开始后可以修改类结构
Boot-Class-Path
设置引导类加载器搜索的路径列表。查找类的特定于平台的机制失败后,引导类加载器会搜索这些路径。按列出的顺序搜索路径。列表中的路径由一个或多个空格分开。(可选)
Can-Redefine-Classes true
表示能重定义此代理所需的类,默认值为 false(可选)
Can-Retransform-Classes true
表示能重转换此代理所需的类,默认值为 false (可选)
Can-Set-Native-Method-Prefix true
表示能设置此代理所需的本机方法前缀,默认值为 false(可选)
最后通过Maven生成Agent的jar包,然后修改测试目标程序的启动器,添加JVM参数即可
参数示例:-javaagent:F:\code\myCode\agent-test\runtime-agent\target\runtime-agent-1.0-SNAPSHOT.jar=hello
最终效果:
Atas ialah kandungan terperinci Cara menggunakan Agen Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Panduan untuk Square Root di Java. Di sini kita membincangkan cara Square Root berfungsi di Java dengan contoh dan pelaksanaan kodnya masing-masing.

Panduan Nombor Sempurna di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor Perfect dalam Java?, contoh dengan pelaksanaan kod.

Panduan untuk Penjana Nombor Rawak di Jawa. Di sini kita membincangkan Fungsi dalam Java dengan contoh dan dua Penjana berbeza dengan contoh lain.

Panduan untuk Weka di Jawa. Di sini kita membincangkan Pengenalan, cara menggunakan weka java, jenis platform, dan kelebihan dengan contoh.

Panduan untuk Nombor Armstrong di Jawa. Di sini kita membincangkan pengenalan kepada nombor Armstrong di java bersama-sama dengan beberapa kod.

Panduan untuk Nombor Smith di Jawa. Di sini kita membincangkan Definisi, Bagaimana untuk menyemak nombor smith di Jawa? contoh dengan pelaksanaan kod.

Dalam artikel ini, kami telah menyimpan Soalan Temuduga Spring Java yang paling banyak ditanya dengan jawapan terperinci mereka. Supaya anda boleh memecahkan temuduga.

Java 8 memperkenalkan API Stream, menyediakan cara yang kuat dan ekspresif untuk memproses koleksi data. Walau bagaimanapun, soalan biasa apabila menggunakan aliran adalah: bagaimana untuk memecahkan atau kembali dari operasi foreach? Gelung tradisional membolehkan gangguan awal atau pulangan, tetapi kaedah Foreach Stream tidak menyokong secara langsung kaedah ini. Artikel ini akan menerangkan sebab -sebab dan meneroka kaedah alternatif untuk melaksanakan penamatan pramatang dalam sistem pemprosesan aliran. Bacaan Lanjut: Penambahbaikan API Java Stream Memahami aliran aliran Kaedah Foreach adalah operasi terminal yang melakukan satu operasi pada setiap elemen dalam aliran. Niat reka bentuknya adalah
