Search code examples
javareflectionjvmbytecode

Can reflection change the declared type of a field


So I discovered how to Change private static final field using Java reflection a while back and have been using it to modify final fields with reflection ever since, however I then got to wondering why I couldn't apply the same logic to the type for the field. I came up with

public static void changeFieldType(Field field, Class newType){
    try {
        Field typeField = Field.class.getDeclaredField("type");
        typeField.setAccessible(true);
        typeField.set(field, newType);
    } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
        LogUtil.printErr("Failed to edit field type for " + field.getName());
    }
}

However this led me to wondering how this would effect an application if you, say, set the type for a field to Object when it was originally an ArrayList or some other higher level class. Would this create internal errors within the JVM or is this value simply a clone of the JVM's data and changing it would have no effect. Any light you can shed on the subject is greatly appreciated.


Solution

  • You can think of values as things you put in boxes within a crate (the crate representing the whole object, and each box within it representing a field). Reflection lets you change the contents of boxes, but it doesn't let you change the shape of any box, nor the overall shape of the crate. The class' structure is fixed once it's loaded.

    There are ways of changing it on the fly as it's being read from a .class file, though. That process is known as bytecode weaving. Needless to say, it's a bit trickier (for instance, if you change a method to take an int instead of a long, then you also need to change all of the call sites of that method to pass in an int instead of a long).