Does class file format provide support for final keyword in case of using it with variables?
Or does it just deduce the effective finality of a variable from code and JIT compiler perform optimization based on it?
Here, in class file format documentation, they mentioned about final keyword, but only in case of using it with final block and final class.
There is nothing about final variables.
No, there is no such information encoded in class file.
You may easily verify this by compiling a source file with a
final
local variable and withoutfinal
- the result classes will be identical.However, Java 8 added
MethodParameters
attribute that records information about names and access flags of method arguments. This means, you can check whether a method argument isfinal
or not.Just-in-time compilers do not need to know about
final
locals - they can easily determine the actual scope of any expression. Even if a variable is not final, e.g.the compilers will optimize the code
A
as ifx
is always1
, and the codeB
as ifx
is always2
.Maybe we should first reconsider the term “variable”. In most contexts, the term “variable” includes local variables,
static
and non-static
fields and more than often even array elements (e.g., in the memory model). Since array elements do not support beingfinal
, the answer can only be given for fields and local variables.For fields, there is the
ACC_FINAL
flag, which tells whether the field isfinal
or not. It has different consequences.static final
fields can only be written in the class initializer whereasfinal
instance fields are not only writable in the constructor but also via Reflection with access override. A JVM trying to take a benefit from thefinal
nature of an instance field when optimizing, has to take care to detect reflective modifications.For local variables, there is no
final
flag, in fact, there is not even a formal declaration at all. In the Java byte code, local variables are only indices within the stack frame, reused at will without premonition. So a write to a local variable index could be either, a change of the variable or a reuse of the same index for a new variable, e.g.{ int x=4; } { int y=5; }
may get compiled to the same byte code as{ int x=4; x=5; }
.For the JVM’s optimizer, it doesn’t matter anyway, as it will transform the operations on the local variables into SSA form, so, with the example above, the optimizer will treat the code as having to constants,
c₁:=4
andc₂:=5
, and depending on the position of the subsequent code it can be determined which constant is uses, in other words, it’s more than having “effectively final” variables, even changing variables can be treated like multiplefinal
variables (in the absence of thread synchronization, even changes to heap variables may temporarily get a similar treatment).