Pet*_*eti 6 java instrumentation bytecode byte-buddy
我尝试拦截对方法的调用,并使用Byte Buddy调用Java 8 lambda表达式AgentBuilder,如下所示:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
我正在使用Byte Buddy v0.7.1.
它可以拦截以下Runnable(匿名类):
FunnyFramework.callMeLater(new Runnable() {
@Override
public void run() {
System.out.println("Hello from inner class");
}
});
Run Code Online (Sandbox Code Playgroud)
当然,对对象的任何调用都定义为普通(非匿名)类.但拦截不适用于lambda表达式:
FunnyFramework.callMeLater(() -> {
System.out.println("Hello from lambda");
});
Run Code Online (Sandbox Code Playgroud)
我怎样才能拦截lambda表达式调用?据我所知,在Byte Buddy中没有LambdaInterceptor这样的东西.
Java虚拟机不允许转换表示lambda表达式的类文件.表示lambda表达式的类由所谓的匿名类加载器加载(不要与传统的匿名类混淆)继承另一个类的安全上下文,例如一个加载了匿名类加载器的类,它将加载的类绑定到另一个类Foo可以访问的private方法Foo.此加载使用sun.misc.UnsafeAPI 显式发生.
Byte Buddy挂钩到Java instrumentation API,它允许ClassFileTransformers 的应用程序挂钩到ClassLoaders加载过程.由于匿名类加载器不被认为ClassLoader是常识,因此检测API不允许进行此类检测,因此禁止对lambda表达式进行检测.
对于某些用例来说,这当然是不幸的,但在大多数现实应用中,没有真正需要检测lambda表达式.例如,许多真实世界的仪器应用于使用给定注释注释的方法,这些方法不可能应用于lambda表达式或者比功能接口更复杂的类.
更新:使用Byte Buddy版本1.1.0,可以检测表示lambda表达式的类.为此,Byte Buddy对JVM进行检测,LambdaMetafactory并使用自定义定义替换类生成.要激活此功能,请在构建器中执行以下步骤:
new AgentBuilder.Default()
.with(LambdaInstrumentationStrategy.ENABLED)
Run Code Online (Sandbox Code Playgroud)
请注意,这仅适用于OpenJDK 8u40,在以前的版本中,存在与invokedynamic调用站点相关的错误,导致无法正常工作.
| 归档时间: |
|
| 查看次数: |
927 次 |
| 最近记录: |