Reading the value of the class fields from an instrumented method

295 views
Skip to first unread message

EmGi

unread,
Mar 9, 2016, 3:23:08 PM3/9/16
to Byte Buddy
Hi,
Imagine we instrument method M1 which is defined in Class C1 such that all calls to C1.M1() will be intercepted by the following method:

@RuntimeType
public static Object intercept(@Origin Method m, @SuperCall Callable<?> zuper) throws Exception {

   
try {
            System.out.println("before call");
           
return zuper.call();
       
}
    finally

        {

           
System.out.println("after call);
       
}
}
 

I tried with the following code to read the value of the fields in C1:

for (Field f : zuper.getClass().getDeclaredFields()) {

    f.setAccessible(true);
    System.out.println("** >> " + f.get(zuper.getClass()));
}

However, it raises the following exception:

java.lang.IllegalArgumentException: Can not set Calculator field Calculator$auxiliary$P2q1d35m.argument0 to java.lang.Class
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:55)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36)
    at java.lang.reflect.Field.get(Field.java:379)
    at MethodProfiler.intercept(MethodProfiler.java:44)

Does anybody know how to read the value of the fields?

EmGi

unread,
Mar 9, 2016, 5:00:15 PM3/9/16
to Byte Buddy

Seems zuper.getClass() does not point to the actual runtime instance and I should use @This annotation to refer to the right object.

@RuntimeType
public static Object intercept(@Origin Method m, @SuperCall Callable<?> zuper, @This Object thiz) throws Exception {

 
for (Field f : m.getDeclaringClass().getDeclaredFields()) {
     f
.setAccessible(true);
     
System.out.println (f.getName() + " : " + f.get(thiz));
 
}

 
return zuper.call();

}


However, when I iterate over DeclaredFields of the object (as shown above), besides the class fields, it also includes its methods?

 field1 : 1
 field2
: 2
 cachedValue$KS3GfOdY$35112437
: public java.lang.String java.lang.Object.toString()
 cachedValue$KS3GfOdY$1381757894
: public native int java.lang.Object.hashCode()
 cachedValue$KS3GfOdY$1690562568
: public int Calculator.sum(Product)
 cachedValue$KS3GfOdY$1214606314
: public boolean java.lang.Object.equals(java.lang.Object)
 cachedValue$KS3GfOdY$651330760
: protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException

Is this probably related to some transformation made by ByteBuddy?



Rafael Winterhalter

unread,
Mar 10, 2016, 11:26:04 AM3/10/16
to EmGi, Byte Buddy
Yes, those fields contain references to the methods that are returned
by the @Origin annotated fields. This caching can be disabled by
setting @Origin(cache = false) but looking up a method reference is a
rather expensive operation, so please consider this. The fields in
question are however marked as synthetic so filtering them out is not
too difficult:

Modifier.isSynthetic(field.getModifiers) == true

The Java compiler also adds synthetic fields every now and then so
this is a good practice in the first place.

Best regards, Rafael
> --
> You received this message because you are subscribed to the Google Groups
> "Byte Buddy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to byte-buddy+...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

EmGi

unread,
Mar 10, 2016, 12:24:17 PM3/10/16
to Byte Buddy, ghafa...@gmail.com

Thanks Rafael. Yes, there is a isSynthetic() method on the Field to simply filter out such fields.
BTW, you mentioned that getting a method reference is expensive. Is there any other (less expensive) alternative to access the fields?

Rafael Winterhalter

unread,
Mar 10, 2016, 1:23:21 PM3/10/16
to EmGi, Byte Buddy

You can use the @FieldValue annotation. There is no good way for getting all fields as you attempt it, unfortunately.

Am 10.03.2016 6:24 nachm. schrieb "EmGi" <ghafa...@gmail.com>:

Thanks Rafael. Yes, there is a isSynthetic() method on the Field to simply filter out such fields.
BTW, you mentioned that getting a method reference is expensive. Is there any other (less expensive) alternative to access the fields?

--
Reply all
Reply to author
Forward
0 new messages