I'm trying to change a private static final field with Java Reflection. But it just fail. Did someone have an idea ?
Here's my code :
public class SecuredClass {
private static final String securedField = "SecretData";
public static String getSecretData() { return securedField; }
}
public class ChangeField {
static void setFinalStatic(Field field, Object newValue) throws Exception
{
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~ Modifier.FINAL);
field.set(null, newValue);
}
public static void main(String args[]) throws Exception
{
System.out.println("Before = " + SecuredClass.getSecretData());
Field stringField = SecuredClass.class.getDeclaredField("securedField");
stringField.setAccessible(true);
setFinalStatic(stringField, "Screwed Data!");
System.out.println("After = " + Java_FileMerger_Main.getSecretData());
}
}
And here's my output :
Before = SecretData
After = SecretData
I've tried to remove the SecurityManager with System.setSecurityManager(null); But it didn't change anything. I know this is evil, but i want to get it work. I hope someone could help me.
The semantics of changing final fields via reflection are not defined (cf. specification). It is not guaranteed that a reflective write to a final field will ever be seen when reading from the field.
Especially with static final fields which have a constant assigned (as in your case), the compiler will often inline the constant and thus the field won't be accessed at all during runtime (only when you use reflection).
The SecurityManager is not relevant here. If using reflection would be forbidden by a SecurityManager, the operation would throw an exception, and not fail silently.
The answers to the question Change private static final field using Java reflection provide some more detail, including an example where you can see in the byte code that constants get inlined.