java agent介紹
java agent是jvm插件或者叫做代理吮蛹,她是運行在main方法之前豁生,她內(nèi)定的方法名稱叫premain。
java agent 概述
接下來我們進(jìn)行開發(fā)
-
實現(xiàn)premain方法
package org.xxz; public class AgentMain { public static void premain(String args, Instrumentation inst) { System.out.println('hello java agent'); } }
上面的這段代碼就完成了java agent的第一步了
-
打包
這里我們使用maven的方式進(jìn)行打包肖粮,請看下面的配置文件
<build> <finalName>java-agent</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</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> <addDefaultImplementationEntries>true</addDefaultImplementationEntries> <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> </manifest> <manifestEntries> <Premain-Class>org.xxz.AgentMain</Premain-Class> <Can-Redefine-Classes>true</Can-Redefine-Classes> <Can-Retransform-Classes>true</Can-Retransform-Classes> </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
執(zhí)行上面的運行命令后,在我們控制臺輸出時就會看到hello java agent的字樣哦A髀搿S止佟!
看到這里就結(jié)束了嗎漫试?沒有哦六敬,我們來看一個小例子。驾荣。外构。。秘车。典勇。。
新建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叮趴,不懂得看官可以上官方網(wǎng)站瞧瞧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,
@This Object target,
@Origin Method method,
@AllArguments Object[] args,
@Super Object delegate,
@SuperCall Callable<?> callable) throws Exception {
TraceTime traceTime = method.getAnnotation(TraceTime.class);
if (traceTime == null) {
return callable.call();
}
long start = System.currentTimeMillis();
try {
// 原有函數(shù)執(zhí)行
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就開發(fā)完成了割笙。。。伤溉。般码。是不是很簡單啊。乱顾。板祝。。
接下來走净,我們看看使用方式咯券时。。伏伯。橘洞。。
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炸枣,把上面的拷貝過來哦。弄唧。适肠。。注意包的結(jié)構(gòu)要一樣哦候引。侯养。。背伴。沸毁。
上面介紹了如何命令行使用java-agent.jar,這里我們介紹如何再IDE中使用傻寂,要上圖了哦。携兵。疾掰。。徐紧。
好了静檬,今天的文章到這里就結(jié)束了。并级。拂檩。
最后還來一張運行結(jié)果吧。嘲碧。稻励。。