java agent介绍
java agent是jvm插件或者叫做代理,她是运行在main方法之前,她内定的方法名称叫premain。
java agent 概述
接下来我们进行开发
-
实现premain方法
package org.xxz; public class AgentMain { public static void premain(String args, Instrumentation inst) { System.out.println('hello java agent'); } }
上面的这段代码就完成了java agent的第一步了
-
打包
这里我们使用maven的方式进行打包,请看下面的配置文件
java-agent org.apache.maven.plugins maven-compiler-plugin 1.8 1.8 utf-8 org.apache.maven.plugins maven-assembly-plugin 3.0.0 true org.xxz.AgentMain jar-with-dependencies make-assembly package single -
使用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是如何配置的
4.0.0
org.xxz
java-agent
1.0
1.8.0
1.7.25
net.bytebuddy
byte-buddy
${bytebuddy.version}
org.slf4j
slf4j-api
${slf4j.version}
org.apache.maven.plugins
maven-compiler-plugin
1.8
1.8
utf-8
org.apache.maven.plugins
maven-assembly-plugin
3.0.0
true
org.xxz.AgentMain
jar-with-dependencies
make-assembly
package
single
这里我们使用了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文件
4.0.0
org.xxz
java-agent-test
1.0
org.apache.maven.plugins
maven-compiler-plugin
1.8
1.8
utf-8
这里的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中使用,要上图了哦。。。。。
好了,今天的文章到这里就结束了。。。
最后还来一张运行结果吧。。。。
原文地址:https://blog.uyiplus.com/2018/java-agent-01/