49997

ByteBuddy: newly defined fields not visible through reflection

Question:

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)

Answer1:

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.

Recommend

  • Cannot resolve corresponding jni fuction
  • Codeigniter 2.1 $this->input->set_cookie($some_var); NOT WORKING
  • Testing Angular dynamic page content (ng-if) with Geb
  • What is difference between sched_batch and sched_other scheduling?
  • How to store large queries inside code for ADO.NET project
  • how to inject a file into http request
  • Typolink inside section menu COA
  • Conditional Redirect on Login
  • Failed to find style … in current theme
  • Getting public URL to file in Google Drive using .NET API
  • removeAllCachedResponses can not clear sharedURLCache?
  • Best way for multi-language sites virtual Directories
  • ORA-02253: constraint specification not allowed here
  • How to fix Invalid JWT with JHipster Registry [Docker]?
  • Symfony 1.4 compatible I18N translation system?
  • get value using jquery
  • Transfer file trough SSH tunnel with Java
  • how to transform dataframe that contains list in every row of each column
  • Velocity (VM) template request parameters: Getting GET variables
  • How to use template selector within a ContentPresenter in Windows 8.1
  • Why processBuilder in java hangs after 5 mins?
  • Preparing an Oracle Connection after being retrieved from a ConnectionPool
  • C++11: Why rvalue reference parameter implicitly converted to lvalue
  • How to join two tables from different databases
  • How to define something in JavaScript [closed]
  • Comparing variables with strings bash
  • Amazon Elastick BeanStalk error: Failed to create the AWS Elastic Beanstalk application version
  • Drag and drop unicode TText in DelphiXe4
  • How to decleare char *const argv[] in swift [duplicate]
  • How to get rgb from transparent pixel in js
  • Grails - How to implement a foreign key relationship not using an id column?
  • Capture SIGFPE from SIMD instruction
  • How to use FirstOrDefault inside Include
  • WPF custom control and direct content support
  • Write to .csv file with PHP (Commas in Data Error)