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?
Where is the description of Constant Folding in the Java Language Specification, Java SE 11 Edition (JLS SE 11)?
347 views Asked by Frank Mi AtThere are 3 answers
On
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.
On
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).
The specification does not use the term Constant Folding.
It has the definition of Constant Expressions
The last part does already point out where precalculation of constant expressions is mandatory. When it comes to
caselabels, 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, butshort 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
ConstantValueattribute 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
switchinstruction is normally done using either, thetableswitchor thelookupswitchinstruction, both requiring precalculatedintvalues for thecaselabels. 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.