0

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.

Community
  • 1
  • 1
Dallen
  • 287
  • 5
  • 15
  • 1
    short answer: no. it is not possible to change variable's type, nor is it possible to change its scope (e.g. make it static) – Sharon Ben Asher Jan 03 '17 at 07:42
  • 1
    Only Instrumentation can do, if the JVM supports it. The mainstream JVMs don’t support this at all. – Holger Jan 03 '17 at 11:07

2 Answers2

3

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).

yshavit
  • 42,327
  • 7
  • 87
  • 124
0

Instrumentation can change the type provided the class hasn't been loaded yet. Once a class has been loaded changing the type is much harder.

Using Unsafe you can access the memory as you wish, swapping int for Object reference, but this is entirely use at your own risk.

Note: changing the type of the reference from List to Object at runtime wouldn't change the type of the actual object referenced.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130