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中使用,要上圖了哦。。。。。
好了,今天的文章到這裏就結束了。。。
最後還來一張運行結果吧。。。。