I haven't read all the links mrlight provided
But I simply would assume the JIT to inline the final field, so if you change it via reflection, the field is changed, but the inlined values are not. Maybe this could be verified with -Xint while executing the testcase (can't try it for myself atm).
Yep, that's exactly what is happening.
Inlining of constants is a rather annoying compile-time optimisation that pre-dates the many run-time optimisations that now exist.
I say annoying, because it makes recompilation of individual classes that contain public final values dangerous - as any other class referencing them (that is not part of the same recompilation) will not use the new values.
I would hope that if Java were ever to be rewritten from scratch, this mistake would not be repeated - optimisations that compromise encapsulation should be deferred until run-time, where their implications upon reflection & hotspot can be managed safely.