I have been faced in some of my Unit test with a strange behaviour with Reflection on final static field. Below is an example illustrating my issue.
I have a basic Singl
It's because of the JIT optimization. To prove this, disable it using the following VM
option:
-Djava.compiler=NONE
In this case all 10_000
iterations will work.
Or, exclude the BasicHolder.getVALUE
method from being compiled:
-XX:CompileCommand=exclude,src/main/BasicHolder.getVALUE
What actually happens under the hood is that after nth
iteration, the hot method getVALUE
is being compiled and static final Integer VALUE
is being aggressively optimized (this is really the just-in-time constant1). From this point, the assertion starts to fail.
The output of the -XX:+PrintCompilation
with my comments:
val 1 # System.out.println("val " + BasicHolder.getInstance().getVALUE());
val 2
val 3
...
922 315 3 src.main.BasicHolder::getInstance (4 bytes) # Method compiled
922 316 3 src.main.BasicHolder::getVALUE (4 bytes) # Method compiled
...
val 1563 # after compilation
val 1563
val 1563
val 1563
...
1 - JVM Anatomy Park: Just-In-Time Constants.