Java Reflection, changing private static final field did nothing

I am trying to change a private static destination field with Java Reflection. But he just fails. Does anyone have an idea?

Here is 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 is my conclusion:

 Before = SecretData After = SecretData 

I tried uninstalling SecurityManager using System.setSecurityManager (null); But that didn’t change anything. I know this is evil, but I want to make it work. Hope someone can help me.

+4
source share
3 answers

The semantics of changing finite fields through reflection is not defined (see specification ). It is not guaranteed that when reading from a field, reflection in the final field will ever be seen.

Especially with static end fields that have a constant binding (as in your case), the compiler often introduces a constant, and thus the field will not be accessible at all at runtime (only when using reflection).

In this case, the SecurityManager does not matter. If the use of reflection is prohibited by the SecurityManager, the operation will throw an exception and will not fail silently.

Answers to the question Changing a private static final field using Java reflection provides more detailed information, including an example where you can see in byte code that the constants get inlined.

+6
source

I also had problems with the above example. For me, this worked after I did not define the string as a literal, but as an object.

 private static final String SECURED_FIELD = String.valueOf("SecretData"); 

or

 private static final String SECURED_FIELD = new String("SecretData"); 

Not the best solution if you want to use literals, but I did not need to take care of this.

+1
source

There is work for this. if you set the value of the private static final file in the static block {}, it will work because it will not embed the field:

 private static final String MY_FIELD; static { MY_FIELD = "SomeText" } ... Field field = VisitorId.class.getDeclaredField("MY_FIELD"); field.setAccessible(true); field.set(field, "fakeText"); 
+1
source

Source: https://habr.com/ru/post/1397746/


All Articles