java agent-02-Java Instrumentation API

server/2024/12/15 7:09:05/

java-agent-系列">java agent 系列

java agent 介绍

java agent-02-Java Instrumentation API

java agent-03-Java Instrumentation 结合 bytekit 实战笔记 agent attach

java agent-03-Java Instrumentation 结合 bytekit 实战笔记 agent premain

java-instrumentation-api">介绍一下 Java Instrumentation API

Java Instrumentation API是Java平台提供的一组API,它允许开发者在运行时通过修改字节码来监测和改变Java应用程序的行为。

这个API在Java SE 5(JDK 5)引入,为开发者提供了访问和操作类加载、字节码修改和类转换的能力,使得在Java应用程序运行时进行动态修改成为可能。

Java Instrumentation API的主要组成部分包括两个接口:InstrumentationClassFileTransformer

  1. Instrumentation接口

    Instrumentation接口是Java Instrumentation API的核心部分,它位于java.lang.instrument包中。

    该接口允许代理程序(即Java代理)与JVM进行交互,并在类加载过程中对类进行修改。

    通过Instrumentation接口,代理程序可以实现以下功能:

    • 获取已加载的类信息,包括类的名称、方法、字段等。
    • 修改类的字节码,实现对类的增强和拦截。
    • 动态定义新的类。
    • 获取和修改类加载器,实现自定义类加载器的功能。

    要使用Instrumentation接口,代理程序需要在premainagentmain方法中获取一个Instrumentation实例。这些方法是Java代理程序的入口点,premain在应用程序启动时调用,agentmain在应用程序运行时动态加载代理时调用。

  2. ClassFileTransformer接口ClassFileTransformer接口是用于在类加载过程中修改类字节码的关键接口。它位于java.lang.instrument包中。

    通过实现ClassFileTransformer接口,代理程序可以在类被加载之前或之后,对类的字节码进行修改。在类加载期间,JVM会调用ClassFileTransformertransform方法,代理程序可以在该方法中实现对类字节码的修改,并返回修改后的字节码。

    ClassFileTransformer接口的方法:

    java">byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException;
    • loader:表示加载当前类的类加载器。
    • className:表示正在加载的类的全限定名。
    • classBeingRedefined:表示正在重定义的类的Class对象,若不是重定义,则为null。
    • protectionDomain:表示保护该类域的域对象。
    • classfileBuffer:表示类的字节码内容。

Java Instrumentation API为开发者提供了强大的能力,使得在Java应用程序运行时对类进行修改和增强成为可能。

但同时也需要注意,使用Java Instrumentation API需要小心谨慎,确保代理程序的操作是合理的,并且不会影响应用程序的稳定性和安全性。

入门例子

代码

实现接口

java">package com.github.houbb.agent.learn.agent;import com.github.houbb.agent.learn.transfer.MyTransformer;import java.lang.instrument.ClassDefinition;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
import java.util.jar.JarFile;public class MyAgent implements Instrumentation {@Overridepublic void addTransformer(ClassFileTransformer transformer, boolean canRetransform) {}@Overridepublic void addTransformer(ClassFileTransformer transformer) {}@Overridepublic boolean removeTransformer(ClassFileTransformer transformer) {return false;}@Overridepublic boolean isRetransformClassesSupported() {return false;}@Overridepublic void retransformClasses(Class<?>... classes) throws UnmodifiableClassException {}@Overridepublic boolean isRedefineClassesSupported() {return false;}@Overridepublic void redefineClasses(ClassDefinition... definitions) throws ClassNotFoundException, UnmodifiableClassException {}@Overridepublic boolean isModifiableClass(Class<?> theClass) {return false;}@Overridepublic Class[] getAllLoadedClasses() {return new Class[0];}@Overridepublic Class[] getInitiatedClasses(ClassLoader loader) {return new Class[0];}@Overridepublic long getObjectSize(Object objectToSize) {return 0;}@Overridepublic void appendToBootstrapClassLoaderSearch(JarFile jarfile) {}@Overridepublic void appendToSystemClassLoaderSearch(JarFile jarfile) {}@Overridepublic boolean isNativeMethodPrefixSupported() {return false;}@Overridepublic void setNativeMethodPrefix(ClassFileTransformer transformer, String prefix) {}// main 方法用于注册 MyAgentpublic static void premain(String agentArgs, Instrumentation inst) {inst.addTransformer(new MyTransformer());}}

最核心的就是最下面的方法。

java">package com.github.houbb.agent.learn.transfer;import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;public class MyTransformer implements ClassFileTransformer {@Overridepublic byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {//只处理自定义的类if(className.startsWith("com")) {// 在此处对类的字节码进行增强,这里只是简单打印类名System.out.println("Transforming class: " + className);}return classfileBuffer;}}

我们只针对 com 开头的方法进行增强。

配置 MANIFEST.MF

我们新建一个文件 src\main\resources\META-INF\MANIFEST.MF,内容如下:

Manifest-Version: 1.0
Premain-Class: com.github.houbb.agent.learn.agent.MyAgent

需要指定我们定义的 Agent 路径。

打包

mvn clean install

生成的 agent jar 完整路径:

D:/code/learn/agent-learn/target/agent-learn-1.0-SNAPSHOT.jar

maven 插件

第一次测试的时候,发现自定义的 MANIFEST.MF 并没有被打包到最总的 jar 中,会导致找不到 Agent 信息。

我们可以在 pom 中指定:

<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.2.2</version><configuration><archive><manifestEntries><build-time>${maven.build.timestamp}</build-time></manifestEntries><manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile></archive></configuration></plugin></plugins>
</build>

定义测试代码

测试方法

我们创建一个简单的测试类

java">package com.github.houbb.agent.learn.test;public class Main {public static void main(String[] args) {System.out.println("Hello world!");}
}

测试

1) 编译

mvn clean compile

编译上面的类,然后到 classes 目录下

2) 运行

java -javaagent:D:/code/learn/agent-learn/target/agent-learn-1.0-SNAPSHOT.jar -cp .  com.github.houbb.agent.learn.test.Main

效果如下

PS D:\code\learn\agent-learn-test\target\classes> java -javaagent:D:/code/learn/agent-learn/target/agent-learn-1.0-SNAPSHOT.jar -cp .  com.github.houbb.agent.learn.test.Main
Transforming class: com/github/houbb/agent/learn/test/Main
Hello world!

参考资料

https://blog.csdn.net/xixi8865/article/details/23849125


http://www.ppmy.cn/server/150292.html

相关文章

基于STM32单片机智能手表GSM短信上报GPS定位温湿度检测记步设计设计

基于STM32单片机智能手表GSM短信上报GPS定位温湿度检测记步设计 1、项目简介 1.1 系统功能1.2 演示视频 2、部分电路设计 2.1 STM32单片机核心板电路设计2.2 UBLOX模块 NEO-6M GPS定位电路设计2.3 ADXL345倾角传感器模块电路设计2.4 SIM900系列短信模块电路2.5 LCD1602液晶显示…

caddy的负载均衡和主动健康检测-会议签到的调优

前期刚实现了rust的前端后台关键业务.结果出现了两类大问题停止服务.在正用着的时候,真是刺激.本来以为的一天搞定,没啥难度,没想到出现这么多意外. 意外原因 1, ip2sta的配置没有在原服务重启后,设定到redis,导致rust后台无法取到,修改原flask初始redis的代码才解决,一天过去了…

探索 Cesium 的未来:3D Tiles Next 标准解析

探索 Cesium 的未来&#xff1a;3D Tiles Next 标准解析 随着地理信息系统&#xff08;GIS&#xff09;和 3D 空间数据的快速发展&#xff0c;Cesium 作为领先的开源 3D 地球可视化平台&#xff0c;已成为展示大规模三维数据和进行实时渲染的强大工具。近年来&#xff0c;随着…

springboot427民航网上订票系统设计和实现(论文+源码)_kaic

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装民航网上订票系统软件来发挥其高效地信息处理的作用&#x…

高中数学:随机变量-正态分布

文章目录 一、连续性随机变量二、大致图像三、正态分布图像及解析式图像特点均值与方差公式正态分布各区域概率 一、连续性随机变量 二、大致图像 三、正态分布图像及解析式 图像特点 均值与方差公式 正态分布各区域概率

Day22 C++ 数据抽象

2024.12.14 C 数据抽象 C 数据抽象 数据抽象是指&#xff0c;只向外界提供关键信息&#xff0c;并隐藏其后台的实现细节&#xff0c;即只表现必要的信息而不呈现细节。 数据抽象是一种依赖于接口和实现分离的编程&#xff08;设计&#xff09;技术。 让我们举一个现实生活中…

css 布局方式

1. 标准流布局&#xff08;Normal Flow&#xff09; 描述&#xff1a;这是最基础的布局方式&#xff0c;元素按照文档的顺序从上到下排列&#xff0c;块级元素垂直排列&#xff0c;内联元素水平排列。应用&#xff1a;适用于大部分简单的网页布局。示例&#xff1a; <div&…

【html 常用MIME类型列表】

本表仅列出了常用的MIME类型&#xff0c;完整列表参考文档。 浏览器通常使用 MIME 类型&#xff08;而不是文件扩展名&#xff09;来确定如何处理 URL&#xff0c;因此 Web 服务器在响应头中添加正确的 MIME 类型非常重要。 如果配置不正确&#xff0c;浏览器可能会曲解文件内容…