字节码编程bytebuddy之结合javaagent监控方法执行耗时
本文看下通过bytebuddy结合javaagent如何实现监控方法耗时功能。
·
写在前面
源码 。
本文看下通过bytebuddy结合javaagent如何实现监控方法耗时功能。
1:程序
首先写agent入口程序:
package com.dahuyou.monitor.method;
//import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.agent.builder.AgentBuilder;
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;
public class MyPreMain {
public static void premain(String agentArgs, Instrumentation instrumentation) {
System.out.println("the agent args is:" + agentArgs);
AgentBuilder.Transformer transformer = (builder, typeDescription, classLoader, javaModule) -> {
// 主要设置代理,以及拦截的方法(拦截的方法不太清楚为什么要在这里设置,不应该和设置要拦截的类在一起吗?)
return builder.method(ElementMatchers.any())
.intercept(MethodDelegation.to(MyByteBuddyDelegator.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("com.dahuyou.monitor.method")) // 指定要拦截的类包前缀
.transform(transformer)
.with(listener)
.installOn(instrumentation);
}
/**
* 有public static void premain(String agentArgs, Instrumentation instrumentation)这个方法,本方法不会被调用
* @param agentArgs
*/
public static void premain(String agentArgs) {}
}
通过builder.method(ElementMatchers.any())
定义要拦截的方法,这里拦截所有方法,.type(ElementMatchers.nameStartsWith("com.dahuyou.monitor.method"))
定义要拦截的包路径前缀。intercept(MethodDelegation.to(MyByteBuddyDelegator.class))
指定代理类为
MyByteBuddyDelegator,符合过滤规则的方法会执行该类,源码如下:
package com.dahuyou.monitor.method;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
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;
/**
* byte buddy 执行代理类
*/
public class MyByteBuddyDelegator {
@RuntimeType
public static Object intercept(@Origin Method method, @SuperCall Callable<?> callable, @AllArguments Object[] args) throws Exception {
long start = System.currentTimeMillis();
try {
// 执行原方法逻辑
return callable.call();
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("方法: " + method + ", 执行耗时:" + (System.currentTimeMillis() - start) + " 毫秒");
}
return null;
}
}
接着就可以来打包测试了,首先来打包:
测试类:
package com.dahuyou.monitor.method;
public class ApiTest {
public static void main(String[] args) throws InterruptedException {
ApiTest apiTest = new ApiTest();
apiTest.echoHi();
}
public ApiTest() {
}
private void echoHi() throws InterruptedException {
System.out.println("hi agent");
Thread.sleep((long) (Math.random() * 500));
}
}
配置agent:
运行:
the agent args is:agent
hi agent
方法: private void com.dahuyou.monitor.method.ApiTest.echoHi() throws java.lang.InterruptedException, 执行耗时:408 毫秒
方法: public static void com.dahuyou.monitor.method.ApiTest.main(java.lang.String[]) throws java.lang.InterruptedException, 执行耗时:408 毫秒
Process finished with exit code 0
写在后面
参考文章列表
更多推荐
所有评论(0)