gpt4 book ai didi

java - 使用 Byte Buddy 拦截对 Java 8 lambda 表达式的调用

转载 作者:搜寻专家 更新时间:2023-10-31 19:44:50 25 4
gpt4 key购买 nike

我尝试使用 Byte Buddy AgentBuilder 拦截对方法的调用和对 Java 8 lambda 表达式的调用,如下所示:

static {
final Instrumentation inst = ByteBuddyAgent.install();
new AgentBuilder.Default()
.type(ElementMatchers.nameContainsIgnoreCase("foo"))
.transform((builder, typeDescription) ->
builder.method(ElementMatchers.any())
.intercept(MethodDelegation.to(LogInterceptor.class)))
.installOn(inst);
}

public static class LogInterceptor {
@RuntimeType
public static Object log(@SuperCall Callable<?> superCall) throws Exception {
System.out.println("yeah...");
return superCall.call();
}
}

我正在使用 Byte Buddy v0.7.1。

它可以拦截以下Runnable(匿名类):

FunnyFramework.callMeLater(new Runnable() {
@Override
public void run() {
System.out.println("Hello from inner class");
}
});

当然还有对定义为普通(非匿名)类的对象的任何调用。但拦截不适用于 lambda 表达式,例如:

FunnyFramework.callMeLater(() -> {
System.out.println("Hello from lambda");
});

如何拦截 lambda 表达式调用?据我所知,字节好友中没有 LambdaInterceptor 这样的东西。

最佳答案

Java 虚拟机不允许转换表示 lambda 表达式的类文件。表示 lambda 表达式的类由所谓的 anonymous class loaders 加载。 (不要与经典的 anonymous classes 混淆)继承另一个类的安全上下文,例如使用匿名类加载器加载的类将加载的类绑定(bind)到另一个类 Foo 可以访问 Fooprivate 方法。这种加载是使用 sun.misc.Unsafe API 显式发生的。

Byte Buddy Hook 到 Java instrumentation API它允许 ClassFileTransformer 的应用程序挂接到 ClassLoader 的加载过程。由于匿名类加载器在常识中不被视为ClassLoader,因此检测 API 不允许此类检测,因此禁止检测 lambda 表达式。

这对于某些用例来说当然是不幸的,但在大多数现实生活中的应用程序中,并没有真正需要检测 lambda 表达式。例如,许多现实世界的检测应用于使用给定注释进行注释的方法,而这些方法不可能应用于 lambda 表达式或比功能接口(interface)更复杂的类。


更新:使用 Byte Buddy 1.1.0 版,可以检测表示 lambda 表达式的类。为此,Byte Buddy 检测了 JVM 的 LambdaMetafactory 并用自定义定义替换了类生成。要激活此功能,请在构建器中执行以下步骤:

new AgentBuilder.Default()
.with(LambdaInstrumentationStrategy.ENABLED)

请注意,这仅适用于 OpenJDK 8u40,在以前的版本中,有一个与 invokedynamic 调用站点相关的错误阻止了它的工作。

关于java - 使用 Byte Buddy 拦截对 Java 8 lambda 表达式的调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33912026/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com