我在代理中使用 ByteBuddy 向测试程序中的每个 Runnable 添加跟踪变量:
new AgentBuilder.Default()
.with(AgentBuilder.LambdaInstrumentationStrategy.ENABLED)
.type(ElementMatchers.isSubTypeOf(Runnable.class)
.and(ElementMatchers.not(ElementMatchers.isInterface())))
.and(ElementMatchers.not(ElementMatchers.isAbstract()))
.transform((builder, typeDescription, classLoader, module) -> builder
.defineField("foo", String.class)
.constructor(ElementMatchers.any())
.intercept(Advice.to(TestRunnableConstructorInterceptor.class))
.method(ElementMatchers.named("run"))
.intercept(Advice.to(TestRunnableRunInterceptor.class))
)
我的拦截器类如下所示:
public static class TestRunnableConstructorInterceptor {
@Advice.OnMethodExit
public static void intercept(@Advice.This Object thiz, @Advice.FieldValue(value="foo",readOnly=false) String foo) throws Exception {
foo = "baz"; // this sets the value successfully
}
}
public static class TestRunnableRunInterceptor {
@Advice.OnMethodEnter
public static void intercept(@Advice.This Object thiz, @Advice.FieldValue("foo") String foo) throws Exception {
System.out.println(foo); //prints "baz"
thiz.getClass().getField("foo"); // java.lang.NoSuchFieldException
}
}
我可以看到 ByteBuddy 正在通过 FieldValue 注释传递新定义的字段,但反射地该变量不可见 - 也许是因为反射应用于原始类,而不是“重新设置”的类?
这是预期的行为吗?有没有办法通过反射访问这个新字段?
这可能与 Runnables 是 lambda 有关吗?我使用的是 Advice 而不是 MethodDelegation,因为如果我尝试在 Runnable#run 上使用 MethodDelegation,我会收到这样的错误(来自我的拦截侦听器)
Failed to transform java.util.concurrent.ThreadPoolExecutor$Worker$auxiliary$8cXEOSRS$auxiliary$7BgjnLbO (before loading) + Exception: java.lang.IllegalStateException: Cannot resolve type description for java.util.concurrent.ThreadPoolExecutor$Worker$auxiliary$8cXEOSRS Cannot resolve type description for java.util.concurrent.ThreadPoolExecutor$Worker$auxiliary$8cXEOSRSnet.bytebuddy.pool.TypePool$Resolution$Illegal.resolve(TypePool.java:134)