why I can`t use method get(java.lang.reflect.Field#get) before changing field`s modifiers

前端 未结 2 659
孤街浪徒
孤街浪徒 2021-01-20 19:52

java code as follow.

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class Test {
    public static void main(Str         


        
2条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2021-01-20 20:24

    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.

提交回复
热议问题