According to the Java VM Specification, the putstatic bytecode is allowed to modify a final field only
- (1) if the field is declared in the current class (the class that declares the current method) and
- (2) if the putstatic instruction appears in the class or interface initializer method <clinit> of the current class.
Otherwise an IllegalAccessError must be thrown.
Similar, the putfield bytecode is allowed to modify a final field only
- (1) if the field is declared in the current class and
- (2) if the instruction appears in an instance initializer method <init> of the current class.
Otherwise an IllegalAccesError must be thrown.
Currently, HotSpot checks only condition (1) but not (2):
Methods that do not satisfy condition (2) violate the assumptions of the compilers. Compiling such methods results in different behavior of compiled and interpreted code (see a detailed example below).