As far as I know, Java deals with constant variables §4.12.4 by constant folding in compile time. I've tried my best, but I couldn't find its description from JLS. Could anybody tell me where I could find official description of the constant folding process for Java 11?
3 Answers
The specification does not use the term Constant Folding.
It has the definition of Constant Expressions
A constant expression is an expression denoting a value of primitive type or a
String
that does not complete abruptly and is composed using only the following:[…]
Constant expressions of type
String
are always "interned" so as to share unique instances, using the methodString.intern
.A constant expression is always treated as FP-strict (§15.4), even if it occurs in a context where a non-constant expression would not be considered to be FP-strict.
Constant expressions are used as
case
labels inswitch
statements (§14.11) and have a special significance in assignment contexts (§5.2) and the initialization of a class or interface (§12.4.2). They may also govern the ability of awhile
,do
, orfor
statement to complete normally (§14.21), and the type of a conditional operator? :
with numeric operands.
The last part does already point out where precalculation of constant expressions is mandatory. When it comes to case
labels, the compiler is required to report duplicates, hence, it must calculate the values at compile-time. When calculating loops, it must calculate constant boolean expressions to determine code reachability.
Likewise, initializers need precalculation to determine the correctness. E.g. short s = 'a' * 2;
is a correct declaration, but short s = Short.MAX_VALUE + 1;
is not.
A well known use case of constant expressions is the initializer of constant variables. When reading a constant variable, the constant value will be used instead of reading the variable, compare with the Q&A “Does the JLS require inlining of final String constants?”
But this does not imply that “constant folding” is mandatory. In theory, a conforming implementation still could perform the calculation of the constant expression as written in the variable initializer at every place where the variable is used. In practice, the bytecode format leads to a constant folding behavior. The ConstantValue
attribute which is used to record the value of a constant variable in bytecode can only hold a precalculated value. When compiling against an already compiled class file, the original expression of a constant variable is not available to the compiler. It can only use the precalculated value.
Likewise, compiling a switch
instruction is normally done using either, the tableswitch
or the lookupswitch
instruction, both requiring precalculated int
values for the case
labels. A compiler would have to go great length to implement a different strategy.
Also, the compiled format for annotation values can only hold precalculated expressions.

- 285,553
- 42
- 434
- 765
The Java Language Specification defines the semantics of the language; constant folding is a compiler optimisation which does not change the behaviour of a Java program, so it is not specified in the JLS, and does not need to be. It is allowed for an implementation of Java not to do it, or to do it in some circumstances but not others, so long as the compiled program does what the JLS says it should.
That said, the JLS does define the language semantics in such a way as to allow constant folding in more cases without changing the behaviour of the program. The most relevant paragraph is what you presumably refer to in §14.2.4:
A constant variable is a final variable of primitive type or type String that is initialized with a constant expression (§15.28). Whether a variable is a constant variable or not may have implications with respect to class initialization (§12.4.1), binary compatibility (§13.1), reachability (§14.21), and definite assignment (§16.1.1).
The referenced sections about class initialisation, binary compatibility, reachability and definite assignment specifically define the semantics of constant variables differently to other variables; specifically, the behaviours they define are the behaviours you would expect from a compiler which does fold constants. This allows those implementing the specification to do the optimisation without overly constraining how they do it.

- 47,440
- 4
- 68
- 97
-
Now I've understood why the JLS doesn't have it, do you have any idea if other Java official documents have more information of constant folding? – Frank Mi Aug 11 '20 at 01:08
The process for fields is linked from the page linked in the question: https://docs.oracle.com/javase/specs/jls/se11/html/jls-13.html#jls-13.1
A reference to a field that is a constant variable (§4.12.4) must be resolved at compile time to the value V denoted by the constant variable's initializer.
If such a field is static, then no reference to the field should be present in the code in a binary file, including the class or interface which declared the field. Such a field must always appear to have been initialized (§12.4.2); the default initial value for the field (if different than V) must never be observed.
If such a field is non-static, then no reference to the field should be present in the code in a binary file, except in the class containing the field. (It will be a class rather than an interface, since an interface has only static fields.) The class should have code to set the field's value to V during instance creation (§12.5).

- 14,957
- 5
- 49
- 49
-
This allows for constant folding of names which refer to constant variables, but it doesn't account for all cases of constant folding, for example replacing `2 * 3` with `6` at compile-time. – kaya3 Aug 11 '20 at 00:15
-
@kaya3 You're right, I was only thinking of constant fields. – Alex - GlassEditor.com Aug 11 '20 at 00:25