Java : Final oddity
2011/03/14 Leave a comment
Hey, I’m back.
I was captured in optimization facts lately and I ended up chasing the true advantages in using final stuff correctly (in Java of course). But much before I could state I have an opinion, I found myself trapped in a strange JVM… mystery.
What I wanted to understand is if the JVM can listen to our ‘hints’ to take the final stuff and use it inline.
This topic has been subject of many talks, mostly because it’s hard for the JVM to determine whether a field won’t change at runtime or not. This could be obvious at first sight: final fields won’t change. But when reflections come into play, well… you’ll never know.
So can reflections change a final field? This is the question. And the answer is: WHO KNOWS? If you look at this document, you’ll notice it’s a long and painful story.
Since there’s nothing better than trying stuff yourself, I tried to discover it by doing a simple test program.
public class Malicious {
public final int testField = 5;
public static void main(String[] args) throws Exception{
Malicious m = new Malicious();
Field f = m.getClass().getField("testField");
f.setAccessible(true);
f.setInt(m, 7);
System.out.println("f: "+f.getInt(m));
System.out.println("m.testField: "+m.testField);
}
}
Before I tell you the results, let me first say that I used:
- MacOSX 10.6.4
- 1.6.0_22
So you won’t get upset if you get different results on different environments.
RESULTS:
f: 7
m.testField: 5
Honestly, this makes no sense. No security exceptions, nothing, just different values. And of course, if I remove the final keyword, what I get is:
f: 7
m.testField: 7
I’m honestly happy to state that a final field cannot be modified via reflections. I’m less happy to say the behavior is not supported by a homogeneous communication because I only got a security exception when I tried to remove the setAccessible line.