package org.monitor;
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;
public class MonitorAgent {
public static void premain(String agentParam, Instrumentation inst) {
System.out.println("premain监控开始--------->包路径:" + agentParam);
// method指定哪些方法需要被拦截,ElementMathers.any指定了所有的方法,声明intercept拦截器
AgentBuilder.Transformer transformer = new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule javaModule) {
return builder.method(ElementMatchers.<MethodDescription>any())
.intercept(MethodDelegation.to(MonitorIntercept.class));
}
};
/**
* 1.type指定了agent拦截的包名,以[com.monitor]作为前缀
* 2.指定了转换器transformer
* 3.将配置安装到Instrumentation
*/
new AgentBuilder.Default()
.type(ElementMatchers.<TypeDescription>nameStartsWith(agentParam))
.transform(transformer)
.installOn(inst);
}
}
byte-buddy使用demo,无代码侵入的方式,监控记录函数方法运行时间
需积分: 0 105 浏览量
更新于2024-02-04
收藏 2.73MB ZIP 举报
ByteBuddy是一个强大的Java字节码操作库,它允许开发者在运行时动态生成或修改类。这个工具在很多场景下非常有用,比如AOP(面向切面编程)、测试、性能监控以及实现代理类等。本篇文章将深入探讨如何使用ByteBuddy来无代码侵入地监控并记录函数方法的运行时间。
1. **ByteBuddy简介**
ByteBuddy是一个开源库,它的主要功能是动态创建Java类和接口的实例。与Java的反射API相比,ByteBuddy提供了更高效且灵活的方式来操作字节码。它支持JVM的各种版本,并可以用于Java、Kotlin、Scala等基于JVM的语言。
2. **无代码侵入的监控**
在传统的代码监控中,我们通常需要在目标方法前后插入计时代码,这种方式被称为代码侵入。使用ByteBuddy,我们可以避免这种侵入性,通过动态代理生成一个新的类,该类包含对原始方法的调用,并在调用前后添加计时逻辑。
3. **创建代理类**
我们需要创建一个`Advice`,这个`Advice`会在方法调用前后执行。ByteBuddy提供了一个名为`@Advice`的注解,可以用来标记哪些字节码应该在特定的代码位置执行。例如,我们可以在方法调用前记录开始时间,在方法调用后计算并记录运行时间。
4. **定义Advice类**
创建一个名为`ExecutionTimer`的类,其中包含`@Before`和`@After`注解的方法,分别在方法执行前和后运行。在`@After`方法中,我们可以获取方法的运行时间,并将其记录到日志或发送到监控系统。
5. **使用ByteBuddy创建代理**
使用`new ByteBuddy().subclass(原类).method(ElementMatchers.isAnnotatedWith(监控注解)).intercept(Advice.to(ExecutionTimer.class))`这段代码创建代理类。这里的`ElementMatchers.isAnnotatedWith`用于匹配带有特定注解的方法,`Advice.to`则是将我们的`ExecutionTimer`类作为拦截器。
6. **注册并使用代理类**
生成的代理类需要注册到JVM中,然后就可以像使用原类一样使用代理类。这样,所有被监控的方法都会自动进行运行时间记录,而无需修改原有代码。
7. **实际应用**
在`monitorDemo`和`monitor`这两个文件中,可能包含了具体的ByteBuddy实现示例。这些示例可能包括了如何定义和应用`Advice`,以及如何创建和使用代理类的代码。通过阅读和学习这些代码,你可以更好地理解如何在实际项目中应用ByteBuddy进行方法监控。
8. **性能考虑**
虽然ByteBuddy提供了便利的监控手段,但动态生成和使用代理类会带来一定的性能开销。因此,这种监控方式更适合在开发阶段或者只对部分关键方法进行监控,而不是全局开启。
9. **与其他工具的比较**
ByteBuddy可以与AspectJ、ASM等其他字节码操作库相比较。AspectJ提供了更完善的AOP支持,而ASM则更加底层,可以直接操作字节码。选择哪个工具取决于具体需求和项目规模。
10. **总结**
ByteBuddy以其灵活性和高效性在Java字节码操作领域占有一席之地。通过学习和应用这个库,开发者能够以无代码侵入的方式实现各种复杂的代码修改和增强任务,如本文中提到的监控方法运行时间。这不仅可以提高开发效率,还能使代码保持整洁,降低维护成本。