java code as follow.
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Test {
public static void main(Str
Field
lazily creates an object called a FieldAccessor
which is actually responsible for get
and set
operations. This can be seen in the source code for Field.get (archive). You can click on the method getFieldAccessor
to go deeper in to the call stack. This will (at the moment) eventually take you to a method sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor (archive) where you can see that the modifiers are read once and then baked in to the actual type of the field accessor.
Calling Field.get
before changing the modifiers affects the output because it causes the field accessor to be instantiated before final
is removed.
You could possibly use something like the following bit of code to clear the field accessors:
public static void clearFieldAccessors(Field field)
throws ReflectiveOperationException {
Field fa = Field.class.getDeclaredField("fieldAccessor");
fa.setAccessible(true);
fa.set(field, null);
Field ofa = Field.class.getDeclaredField("overrideFieldAccessor");
ofa.setAccessible(true);
ofa.set(field, null);
Field rf = Field.class.getDeclaredField("root");
rf.setAccessible(true);
Field root = (Field) rf.get(field);
if (root != null) {
clearFieldAccessors(root);
}
}
Using that causes the code in the question to pass, if you insert clearFieldAccessors(field)
in between field.get(...)
and field.set(...)
.
There is, of course, no guarantee that any of this has to work, and it's possible that the code in clearFieldAccessors
will cause some problem that I'm unaware of.