这是预期的行为吗?有没有办法通过反射访问这个新字段?这可能与 Runnables 是 lambdas 有关系吗?我使用的是 Advice 而不是 MethodDelegation 因为如果我尝试在 Runnable#run 上使用 MethodDelegation 我会收到这样的错误(来自我的拦截侦听器)未能转换 java.util.concurrent.ThreadPoolExecutor$Worker$auxiliary$8cXEOSRS$auxiliary$7BgjnLbO(加载前)+异常:java.lang.IllegalStateException:无法解析 java.util.concurrent 的类型描述.ThreadPoolExecutor$Worker$auxiliary$8cXEOSRS 无法解析 java.util.concurrent.ThreadPoolExecutor$Worker$auxiliary$8cXEOSRSnet.bytebuddy.pool.TypePool$Resolution$Illegal.resolve(TypePool.java:134) 的类型描述 解决方案 如评论中所述,您需要使用 getDeclaredField 方法而不是 getField定位非公共字段.我假设您的 MethodDelegation 会在您检测任何 Runnable 时呈现错误.您是否在委托方法中请求 @SuperMethodCall 代理?在这种情况下,您正在指示 Byte Buddy 也检测这些类,因为它们的字节码没有持久化.通常,Byte Buddy 从检测中排除合成类.当您检测 java.* 命名空间时,我假设您没有使用默认的排除匹配器?理想情况下,您应该限制检测类型的空间,例如通过名称,您还可以排除包含 $auxiliary$ 的类.否则,您仍然可以按默认方式排除合成类.I use ByteBuddy in an Agent to add a tracking variable to each Runnable in a test program: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)) )With my Interceptor classes looking like this: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 }}I can see that ByteBuddy is passing through the newly defined field via the FieldValue annotation, but reflectively the variable is not visible - perhaps because the reflection is being applied to the original class, and not the 'rebased' class?Is this the expected behavior? Is there a way to access this new field via reflection?Could this be something to do with the Runnables being lambdas? I'm using Advice rather than MethodDelegation because if I try to use MethodDelegation on Runnable#run I get errors like this (from my interception Listener)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) 解决方案 As mentioned in the comments, you need to use the getDeclaredField method instead of getField when you want to locate non-public fields.I assume that your MethodDelegation renders errors as you instrument any Runnable. Do you request @SuperMethodCall proxies in your delegation method? In this case, you are instructing Byte Buddy to also instrument these classes what is impossible as their byte code is not persisted.Normally, Byte Buddy excludes synthetic classes from instrumentation. As you instrument the java.* namespace, I assume that you are not using the default exclusion matcher? You should ideally restrain your space of instrumented types, for example by name where you could also exclude classes containing $auxiliary$. Otherwise, you can still exclude synthetic classes as it is by default. 这篇关于ByteBuddy:新定义的字段通过反射不可见的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 08-21 08:16