bytecode - 关于如何正确有效地使用 ByteBuddy 的指南
问题描述
我查看了 ByteBuddy 文档,还查看了一些使用 ByteBuddy 的 Java 代理实现。但是我仍然不太清楚什么是使用 ByteBuddy 代理的正确方法。
这是我用来引导代理的代码:
public class ByteBuddyAgent {
public static void premain(String arguments, Instrumentation instrumentation) {
System.out.println("Bootstrapping ByteBuddy Agent");
new AgentBuilder.Default()
.with(new AgentBuilder.InitializationStrategy.SelfInjection.Eager())
.type(ElementMatchers.hasSuperClass(ElementMatchers.nameContains("Level1")))
.transform(new ByteBuddyTransformer()
.installOn(instrumentation);
}
private static class ByteBuddyTransformer implements AgentBuilder.Transformer{
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription,
ClassLoader classLoader, JavaModule module) {
return builder.method(ElementMatchers.named("printLevel"))
.intercept(Advice.to(MethodTracker.class));
}
}
}
这是我的 Advice 课程,我在其中尝试了 Advice 支持的不同注释,并且效果很好。
public class MethodTracker {
@Advice.OnMethodEnter
public static Object onMethodBegin(@Advice.This Object invokedObject, @Advice.AllArguments Object[] arguments,
@Advice.FieldValue("name") Object fieldValue, @Advice.Origin Object origin,
@Advice.Local("localVariable") Object localVariable) {
System.out.println("=======on Method Begin Running with ByteBuddy=======, " + invokedObject);
System.out.println("======Printing arguments=======");
for(Object obj: arguments){
System.out.println("Argument:: " + obj);
}
localVariable = "Gunika";
System.out.println("FieldValue:: " + fieldValue);
System.out.println("Origin:: " + origin);
return "ReturningStateFromOnMethodBegin";
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void onMethodEnd(@Advice.This Object invokedObject, @Advice.Return Object returnValue,
@Advice.FieldValue("name") Object fieldValue, @Advice.Enter Object state,
@Advice.Local("localVariable") Object localVariable){
System.out.println("=======on Method End Running with ByteBuddy======= " + invokedObject);
System.out.println("Return value is " + returnValue);
System.out.println("FieldValue:: " + fieldValue);
System.out.println("FieldValue:: " + fieldValue);
System.out.println("State:: " + state);
System.out.println("LocalVariable:: " + localVariable);
}
}
我的问题如下:
现在在我的示例应用程序中,我刚刚尝试匹配 1 条规则。但是,如果有“n”条规则,我想立即应用什么来实现这一点。
有一组初始规则应用于/提供给代理。现在让我们说在某个时间点我想添加另一个规则。实现这一目标的正确方法是什么?
我们创建的 AgentBuilder 实例是否应该在 Java 代理中只创建一次?
使用 ByteBuddy 代理时应注意的任何其他信息都会有所帮助。
解决方案
Advice.to(MethodTracker.class)
很贵。如果您检测许多类并想消耗内存,我建议您重用该实例,它是不可变的。
除此之外@Advice.AllArguments
,如果您负担得起的话,它比使用读取特定参数的专门建议类更昂贵。然而,这是一个 JVM 问题,而不是 Byte Buddy 特定的问题。您可以使用-Dnet.bytebuddy.dump=/some/folder
查看生成的字节码。昂贵的东西往往掩盖了你想要的结构。
推荐阅读
- flutter - 有什么方法可以依赖颤动的 pubspec 中的任何 git 引用吗?
- php - Woocommerce - 找出购物车中的商品超过 50 公斤
- java - 如何在字符串数组中找到公平索引的字母
- python - 如何根据 Pandas 中“Col1”之后创建的列更新“Col1”列的值
- javascript - editorconfig 不保留 Github Repo 文件的格式
- python - 如何让 Selenium 始终打开同一个应用程序的应用程序超链接?
- c++ - C ++字符串比较帮助我
- laravel - Laravel Livewire 事件侦听器未触发
- bootstrap-4 - 显示 -1 溢出 jumbotron (Bootstrap 4)
- html - 如果里面的内容占用的空间比剩余空间多,如何使 flex 元素占据剩余空间而不增长?