Sun Java Solaris Communities My SDN Account
 
The Java Language Specification

Clarifications and Amendments to the JLS

 

The Java Language Specification


The Java programming language has evolved since the publication of the The Java Language Specification. Here is a brief overview of changes made to the Java platform in JDK 1.1(Originally published as Appendix D from The Java Programming Language by Ken Arnold).

The most significant language change has been:

  1. The addition of nested classes (often called inner classes).  For more comprehensive details, see the nested classes specification. The nested classes specification has itself required these clarifications over time.
  2. The changes to floating point semantics. Those sections of the JLS (1st edition) that have been affected by the floating point changes are listed here (in PDF format). Changes are highlighted using change bars.
In addition, various questions have arisen over time with respect to The Java Language Specification. This has prompted us to issue a series of clarifications and amendments to the specification, given below. We will be issuing amendments on an ongoing basis, as the need arises.

Please send us any technical remarks. We look forward to your comments. 

Package Naming Conventions

JLS 7.7 discusses recommended conventions for package names and states that the first component of a unique package name should be written in uppercase letters. This is no longer the recommended convention. The relevant text should be revised to state:

The first component of a unique package name is always written in all-lowercase ASCII letters and should be one of the top-level domain names, currently com, edu, gov, mil, net, org, or one of the English two-letter codes identifying countries as specified in ISO Standard 3166, 1981.

Method Override

The specification of when a method of a subclass overrides a method in a superclass given in JLS 8.4.6.1 is revised to state:
An instance method m declared in class C overrides another method m' declared in class C' if and only if the following three conditions hold:
  1. C is a subclass of C' or C = C'.
  2. Either
    1. m' is not private, and is accessible from C, OR
    2. m overrides a method m'', where m'' != m and m'' != m', such that m'' overrides m'.
  3. m and m' have the same name and signature.
Here is a rationale for the change.

Interface Member Modifiers

Several grammar productions were inadvertently omitted from section 9.3 of the JLS, which discusses modifiers on members of interfaces. The beginning of JLS 9.3 should be corrected to read:
ConstantDeclaration:

    ConstantModifiers_opt Type VariableDeclarator



ConstantModifiers:

  ConstantModifier

  ConstantModifier ConstantModifiers



ConstantModifier: one of

  public static final

Every field declaration in the body of an interface is implicitly public,static, and final. It is permitted, but strongly discouraged as a matter of style, to redundantly specify any or all of these modifiers for such fields. It is a compile time error if the same modifier appears more than once in a field declaration.

Arrays implement java.io.Serializable

JLS 10.7 (p. 198) should be amended to state that all arrays implement the interface java.io.Serializable, in addition to the interface Cloneable.

Preparation does not cause AbstractMethodErrors

JLS 12.3.2 should be amended so that AbstractMethodError is not thrown during preparation. The revised section text is:
Preparation involves creating the static fields (class variables and constants) for a class or interface and initializing such fields to the standard default values (§4.5.4). This does not require the execution of any Java code; explicit initializers for static fields are executed as part of initialization (§12.4), not preparation.

Implementations of the Java Virtual Machine may precompute additional data structures at preparation time in order to make later operations on a class or interface more efficient. One particularly useful data structure is a "method table" or other data structure that allows any method to be invoked on instances of a class without requiring a search of superclasses at invocation time.

Resolution of Symbolic References

In JLS 12.3.3 the bullets discussing NoSuchFieldError and NoSuchMethodError should be amended by omitting the restriction that the declaration of the field or method must be local to class and may not be an inherited field or method.

Class Initialization

JLS 12.4.1 should be modified to clarify exactly when class initialization may be initiated. The initial paragraph of JLS 12.4.1 can be restated as follows:
Initialization of a class consists of executing its static initializers  and the initializers for static fields declared in the class. Initialization of an interface consists of executing the initializers for fields declared in the interface.

 Before a class is initialized, its direct superclass must be initialized, but interfaces implemented by the class need not be initialized. Similarly, the superinterfaces of an interface need not be initialized before the interface is initialized.

A class or interface type T will be initialized immediately before the first occurence of any one of the following:

  • T is a class and an instance of T is created.
  • T is a class and a static method of T is invoked.
  • A non-constant static field of T is used or assigned. A constant field is one that is (explicitly or implicitly) both final and static, and that is initialized with the value of a compile-time constant expression. A reference to such a field must be resolved at compile time to a copy of the compile-time constant value, so uses of such a field never cause initialization.
Invocation of certain reflective methods in class java.lang.Class and in package java.lang.reflect also causes class or interface initialization.

Class finalization

Class finalization (JLS 12.7) has been removed from the Java language. The functionality of JLS 12.7 is subsumed by instance finalization (JLS 12.6). Here is a rationale for this decision.

Class Unloading

Questions have arisen with respect to the interpretation of JLS 12.8 "Unloading of Classes and Interfaces". The following statement should help clarify the issue:

 A class or interface may be unloaded if and only if its class loader is unreachable (the definition of unreachable is given in JLS 12.6.1). Classes loaded by the bootstrap loader may not be unloaded.

Here is a brief technical rationale for this statement.
 

Compilation of Symbolic References

Note: this change only applies to compilers targeted at virtual machines that perform a resolution time lookup (see changes to 12.3.3 above). These include the JDK1.1 and 1.2 VMs (but not the JDK1.0.2 VM), and any virtual machine whose version number is 46.0 and above.

The third bullet of JLS 13.1 should be corrected to state the following:

Given a legal field access expression in a class C referencing a field f declared in another class:
If the expression is of the form

Primary.f

then let T be the type of Primary. T must be some reference type denoting a class or interface.

If the expression is of the form

super.f

then let T be the superclass of C.
 

The reference to f must be compiled into a symbolic reference to the class or interface T, plus the simple name of the field, f. The reference must also include a symbolic reference to the declared type of the field so that the verifier can check that the type is as expected. References to fields that are static, final, and initialized with compile-time constant expressions are resolved at compile time to the constant value that is denoted. No reference to such a constant field should be present in the code in a binary file (except in the class or interface containing the constant field, which will have code to initialize it), and such constant fields must always appear to have been initialized; the default initial value for the type of such a field must never be observed. See §13.4.8 for a discussion.

Similarly, the fourth bullet of JLS 13.1 should be corrected as follows:
Given a method invocation expression in a class C referencing a method m declared in another class:
If the expression is of the form

Primary.m

then let T be the type of Primary. T must be some reference type denoting a class or interface.

If the expression is of the form

super.f

then let T be the superclass of C.

If the expression is of the form

X.m

then X must be the name of a class or interface. Let T be the class or interface denoted by X.
 

The reference to a method or constructor must be resolved at compile time to a symbolic reference to T, plus the signature of the method or constructor.  A reference to a method must also include either a symbolic reference to the return type of the denoted method or an indication that the denoted method is declared void and does not return a value.

Here is an explanation why these corrections are necessary.

Obviously, much of JLS 13.4.5 must change in light of the changes to JLS 13.1 and 12.3.3.

Final Fields and Binary Compatibility

In JLS 13.4.8, the first lines of page 251 should be corrected to read:
Suppose that a new version of class Super  is produced:

class Super {final static char s = 'b'; }

If Super is recompiled but not Test, then running the new binary with the existing binary of Test results in an IllegalAccessError.

Volatile Fields and Binary Compatibility

JLS 13.4.11 erroneously states that changing a (non-private) field from volatile to non-volatile or vice versa may cause an IncompatibleClassChangeError. This is untrue, and section 13.4.11 should be disregarded.

Corrrected Method Lookup Algorithm

The method lookup algorithm given in JLS 15.11.4.4 is inaccurate. Here is a reformulation of the algorithm that reflects the semantics given in the rest of the book:
The dynamic method lookup uses the following procedure to search class S, and then the superclasses of class S, as necessary, for method m.
Let X be the type of the target reference of the method invocation.
  • If class S contains a declaration for a non-abstract method named m with the same descriptor (same number of parameters, the same parameter types, and the same return type) required by the method invocation as determined at compile time (§15.11.3), then :
      • If the invocation mode is super or interface, then this is the method to be invoked, and then procedure terminates.
      • If the invocation mode is virtual, and the declaration in S overrides (§8.4.6.1) X.m, then this is the method to be invoked, and the procedure terminates.
    • Otherwise, if S has a superclass, this same lookup procedure is performed recursively using the direct superclass of S in place of S; the method to be invoked is the result of the recursive invocation of this lookup procedure.
    • Otherwise, an AbstractMethodError is raised.

    null is a Compile time Constant

    JLS 15.27 defines the notion of a compile time constant. The definition erroneously excludes null. The beginning of JLS 15.27 should read:
    A compile-time constant expression is an expression denoting a value of primitive type or null or a String that is composed using only the following:

    * Literals of primitive type, null and literals of type String


    Oracle is reviewing the Sun product roadmap and will provide guidance to customers in accordance with Oracle's standard product communication policies. Any resulting features and timing of release of such features as determined by Oracle's review of roadmaps, are at the sole discretion of Oracle. All product roadmap information, whether communicated by Sun Microsystems or by Oracle, does not represent a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. It is intended for information purposes only, and may not be incorporated into any contract.