埋点实现在方法前后动态插入代码,获取方法的执行时间。
常见的方法有以下3钟:
1 硬编码
2 spirng aop 动态代理
3 动态插入字节码
其中 1 和 2 系统代码侵入性大,方法3不用更改系统代码。
JavaAgent是从JDK1.5及以后引入的,在1.5之前无法使用,也可以叫做java代理。利用 java代理,即 java.lang.instrument 做动态 Instrumentation 是 Java SE 5 的新特性,它把 Java 的 instrument 功能从本地代码中解放出来,使之可以用 Java 代码的方式解决问题。
使用 Instrumentation,开发者可以构建一个独立于应用程序的代理程序(Agent),用来监测和协助运行在 JVM 上的程序,甚至能够替换和修改某些类的定义。有了这样的功能,开发者就可以实现更为灵活的运行时虚拟机监控和 Java 类操作了,这样的特性实际上提供了一种虚拟机级别支持的 AOP 实现方式,使得开发者无需对 JDK 做任何升级和改动,就可以实现某些 AOP 的功能了。在 Java SE 6 里面,instrumentation 包被赋予了更强大的功能:启动后的 instrument、本地代码(native code)instrument,以及动态改变 classpath 等等。这些改变,意味着 Java 具有了更强的动态控制、解释能力,它使得 Java 语言变得更加灵活多变。Instrumentation 的最大作用,就是类定义动态改变和操作。
开发者可以在一个普通 Java 程序(带有 main 函数的 Java 类)运行时,通过 -javaagent参数指定一个特定的 jar 文件(包含 Instrumentation 代理)来启动 Instrumentation 的代理程序。开发者可以让 Instrumentation 代理在 main 函数运行前执行premain函数。
基本步骤:
1 编写premian函数
2 将监控程序打包jar,META-INF/MAINIFEST.MF 必须包含 Premain-Class
3 使用java -javaagent:jar 文件的位置 [= 传入 premain 的参数 ]运行被监控的程序
新建项目JAgent
1 增加pom依赖
<dependency> <groupId>jboss</groupId> <artifactId>javassist</artifactId> <version>3.8.0.GA</version></dependency>2 编写permian函数
3 打包jar
<build> <plugins> <!--编译Java源码--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> <!-- 打成jar时,设定manifestEntries的参数 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.0.2</version> <configuration> <archive> <manifestEntries> <Project-name>${project.name}</Project-name> <Project-version>${project.version}</Project-version> <Premain-Class>com.chy.JAgent</Premain-Class> <Can-Redefine-Classes>false</Can-Redefine-Classes> </manifestEntries> </archive> <skip>true</skip> </configuration> </plugin> <!-- 方法1: 包含所有依赖的jar文件,依赖以class的方式存在 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>1.2.1</version> <configuration> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>com.chy.JAgent</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins></build><Premain-Class>com.chy.JAgent</Premain-Class> 指定 premain 函数入口
确保 META-INF/MAINIFEST.MF 必须包含 Premain-Class
新建项目JAgentTest (埋点项目)
配置项目 vm 参数
-javaagent:G:\java\intellij_idea\IdeaProjects\javaByteCode\JAgent\target\JAgent-1.0-SNAPSHOT.jar=JAgent
运行JAgentTest 打印结果如下
premain:JAgent
JAgentTest is run
埋点开始-1
埋点开始-2
begin=1530337378023
JSercice is start
..........
JSercice is end
| 欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) | 黑马程序员IT技术论坛 X3.2 |