java agent介绍java
java agent是jvm插件或者叫作代理,她是运行在main方法以前,她内定的方法名称叫premain。shell
<!-- more -->apache
java agent 概述api
接下来咱们进行开发app
实现premain方法jvm
package org.xxz; public class AgentMain { public static void premain(String args, Instrumentation inst) { System.out.println('hello java agent'); } }
上面的这段代码就完成了java agent的第一步了maven
打包ide
这里咱们使用maven的方式进行打包,请看下面的配置文件函数
<build> <finalName>java-agent</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> <encoding>utf-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.0.0</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> </manifest> <manifestEntries> <Premain-Class>org.xxz.AgentMain</Premain-Class> </manifestEntries> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
使用java agent测试
新建一个maven工程,打包而后运行
java -jar demo.jar -javaagent:/apps/java-agent.jar
执行上面的运行命令后,在咱们控制台输出时就会看到hello java agent的字样哦!!!
看到这里就结束了吗?没有哦,咱们来看一个小例子。。。。。。。
新建maven工程
java-agent --src --main --java --org.xxz --AgentMain.java --TimeInterceptor.java --TraceTime.java --resource --test --pom.xml
首先看看咱们的pom.xml是如何配置的
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.xxz</groupId> <artifactId>java-agent</artifactId> <version>1.0</version> <properties> <bytebuddy.version>1.8.0</bytebuddy.version> <slf4j.version>1.7.25</slf4j.version> </properties> <dependencies> <dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> <version>${bytebuddy.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> <encoding>utf-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.0.0</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> </manifest> <manifestEntries> <Premain-Class>org.xxz.AgentMain</Premain-Class> </manifestEntries> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
这里咱们使用了bytebuddy,不懂得看官能够上官方网站瞧瞧http://bytebuddy.net/
再来看看咱们得AgentMain.java
package org.xxz; import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.implementation.MethodDelegation; import net.bytebuddy.matcher.ElementMatchers; import net.bytebuddy.utility.JavaModule; import java.lang.instrument.Instrumentation; /** * @author tt */ public class AgentMain { public static void premain(String args, Instrumentation inst) { AgentBuilder.Transformer transformer = new AgentBuilder.Transformer() { @Override public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule) { return builder .method(ElementMatchers.any()) // 拦截任意方法 .intercept(MethodDelegation.to(TimeInterceptor.class)); // 委托 } }; AgentBuilder.Listener listener = new AgentBuilder.Listener() { @Override public void onDiscovery(String s, ClassLoader classLoader, JavaModule javaModule, boolean b) { } @Override public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule, boolean b, DynamicType dynamicType) { } @Override public void onIgnored(TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule, boolean b) { } @Override public void onError(String s, ClassLoader classLoader, JavaModule javaModule, boolean b, Throwable throwable) { } @Override public void onComplete(String s, ClassLoader classLoader, JavaModule javaModule, boolean b) { } }; new AgentBuilder .Default() .type(ElementMatchers.nameStartsWith("org.xxz"))// 指定须要拦截的类 .transform(transformer) .with(listener) .installOn(inst); } }
这里咱们看看咱们得TimeInterceptor.java
package org.xxz; import net.bytebuddy.implementation.bind.annotation.Origin; import net.bytebuddy.implementation.bind.annotation.RuntimeType; import net.bytebuddy.implementation.bind.annotation.SuperCall; import java.lang.reflect.Method; import java.util.concurrent.Callable; /** * @author tt */ public class TimeInterceptor { @RuntimeType public static Object interceptor(@Origin Class clazz, @Origin Method method, @SuperCall Callable<?> callable) throws Exception { TraceTime traceTime = method.getAnnotation(TraceTime.class); if (traceTime == null) { return callable.call(); } long start = System.currentTimeMillis(); try { // 原有函数执行 return callable.call(); } finally { System.out.println(clazz.getSimpleName() + "#" + method.getName() + " cost " + (System.currentTimeMillis() - start) + "ms"); } } }
最后就是咱们得注解了TraceTime.java
package org.xxz; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @author tt */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface TraceTime { }
到这里咱们得java-agent就开发完成了。。。。。是否是很简单啊。。。。
接下来,咱们看看使用方式咯。。。。。
java-agent-test --src --main --java --org.xxz --test --AgentMainTest.java --Demo.java --TraceTime.java --resource --test --pom.xml
依旧先看咱们得pom文件
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.xxz</groupId> <artifactId>java-agent-test</artifactId> <version>1.0</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> <encoding>utf-8</encoding> </configuration> </plugin> </plugins> </build> </project>
这里的pom文件上面的简单多了。
看看咱们的测试类AgentMainTest.java
package org.xxz.test; /** * @author tt */ public class AgentMainTest { public static void main(String[] args) throws Exception { Demo demo = new Demo(); demo.print("agent"); } }
看看咱们的Demo.java
package org.xxz.test; import org.xxz.TraceTime; /** * @author tt */ public class Demo { @TraceTime public void print(String string) throws InterruptedException { Thread.sleep(100L); System.out.println("hello " + string); } }
这里还少了一个TraceTime.java,把上面的拷贝过来哦。。。。注意包的结构要同样哦。。。。。
上面介绍了如何命令行使用java-agent.jar,这里咱们介绍如何再IDE中使用,要上图了哦。。。。。
好了,今天的文章到这里就结束了。。。
最后还来一张运行结果吧。。。。