Project Coin/JSR 334 Documentation v0.9375

Table of Contents

Overview

Project Coin/JSR 334 is an effort to add a set of small language changes to Java SE 7 under the JSR 336 umbrella JSR with the reference implementation developed in OpenJDK. The changes must be simultaneously small in specification, implementation, and testing. The small changes to the Java programming language in Java SE 7 are:

A description of the semantics for each feature as implemented in JDK 7 build b143 will follow. Non-normative discussion will appear in block quotes as below:


Discussion: Text appearing here is only informative.


The documentation for a language change includes updates to the Java™ Language Specification, Third Edition (JLSv3) and may also include supporting library changes. Since the changes will in part be phrased as differences from existing JLSv3 text, having the JLSv3 text available to provide context is recommended for a close reading of this document. The full text of JLSv3 is available online. Text that is deleted from JLSv3 will be displayed like this, while text that is added will be rendered this way. The language changes as given in this document may at times be less formal than the eventual JLSv3 updates. Readers should review the discussion section of a feature before sending in a comment or question about that feature. Previous discussions of design considerations may appear in the coin-dev archives.

For informational purposes, a summary of changes to the JSR 269 API in the javax.lang.model.* packages is given in an appendix. Some of the changes have been made to directly support new language features; other changes are usability improvements to the API. These changes have gone through a maintenance review of JSR 269 for inclusion in the JSR 336 umbrella JSR for Java SE 7.

Features

Strings in switch

The list of types which can be switched on in JLSv3 §14.11 "The switch Statement" is augmented to include String:

"The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, String, or an enum type (§8.9), or a compile-time error occurs."

No other explicit changes are necessary to support switching on a string.


Discussion: The lexical grammar of the switch statement does not need to be changed to support switching on a string since the String is already included in the definition of constant expressions, JLSv3 §15.28, so the SwitchLabel production does not need to be augmented. The existing restrictions in JLSv3 §14.11 on no duplicate labels, at most one default, no null labels, etc. all apply to String labels without modification. The definite assignment analysis of the switch statement, JLSv3 §16.2.9, is unchanged as well.

The existing rules for the switch statement forbid a null label and require a NullPointerException to be thrown if the expression being switched on is null. A null expression can occur for both enum types and for boxed primitive types like Integer and Float. Therefore, consistency alone argues for these prohibitions to also be in place when switching on a string.

The prohibition on duplicate string labels applies after any encoding step which maps a sequence of bytes of the input file to a sequence of logical characters and after the specified Unicode escape lexical translations (JLSv3 §3.2) are applied. Therefore, labels that are textually distinct in the source code may still be regarded as being duplicates after these translations occur. Whether or not string labels are distinct may depend on the encoding used by the compiler to interpret the bytes of the input sources.

In order to keep strings in switch a small language change, the JVM lookupswitch and tableswitch instructions in Java SE 7 do not support switching on a string. Instead, Java compilers are responsible for translating a switch on strings into some sequence of byte code instructions with the proper semantics. Many valid and efficient translation schemes are possible that have better expected performance than successive comparisons of the string being switched on with each case label constant. Direct JVM support for switching on a string may be added in a future version of the platform.


Binary integral literals and underscores in numeric literals

Binary integer literals are structured just like hexadecimal integer literals except that binary digits are used instead of hexadecimal digits and binary literals are prefixed by "0b" rather than "0x".

In numeric literals, underscores are allowed as separators between digits. This applies to literals in any supported base: binary, octal, hexadecimal, or decimal and applies both to integer literals (§3.10.1) and floating-point literals (§3.10.2).

The grammar changes below are additions or modifications to JLSv3 §3.10.

IntegerLiteral:
DecimalIntegerLiteral
HexIntegerLiteral
OctalIntegerLiteral
BinaryIntegerLiteral
BinaryIntegerLiteral:
BinaryNumeral IntegerTypeSuffixopt
BinaryNumeral:
0 b BinaryDigits
0 B BinaryDigits
DecimalNumeral:
0
NonZeroDigit Digitsopt
NonZeroDigit Underscores Digits
Underscores:
_
Underscores _
Digits:
Digit
Digits Digit
Digit DigitsAndUnderscoresopt Digit
DigitsAndUnderscores:
DigitOrUnderscore
DigitsAndUnderscores DigitOrUnderscore
DigitOrUnderscore:
Digit
_
HexDigits:
HexDigit
HexDigit HexDigits HexDigitsAndUnderscoresopt HexDigit
HexDigitsAndUnderscores:
HexDigitOrUnderscore
HexDigitsAndUnderscores HexDigitOrUnderscore
HexDigitOrUnderscore:
HexDigit
_
OctalNumeral:
0 OctalDigits
0 Underscores OctalDigits
OctalDigits:
OctalDigit
OctalDigit OctalDigits OctalDigitsAndUnderscoresopt OctalDigit
OctalDigitsAndUnderscores:
OctalDigitOrUnderscore
OctalDigitsAndUnderscores OctalDigitOrUnderscore
OctalDigitOrUnderscore:
OctalDigit
_
BinaryDigits:
BinaryDigit
BinaryDigit BinaryDigitsAndUnderscoresopt BinaryDigit
BinaryDigitsAndUnderscores:
BinaryDigitOrUnderscore
BinaryDigitsAndUnderscores BinaryDigitOrUnderscore
BinaryDigitOrUnderscore:
BinaryDigit
_
BinaryDigit: one of
0 1

No other language changes are necessary to support the new literal syntax.


Discussion: As written, due to reuse of the productions, these grammar changes imply underscores as separators are supported both in integral literals (for int, long, short, etc.) as well as for floating-point literals without explicit changes to the section describing floating-point literals. Therefore allowed uses of underscores include:

while disallowed uses of underscores include:

The grammar above for the literals is unambiguous, but as written requires a lookahead of more than 1 character because the recursion is in the middle of the Digits production. Since the underscores are separators, productions like

Digits:
Digit DigitsAndUnderscoresopt

would not be correct since an underscore could appear as a terminator of the literal. Since the lexical grammar has expository purposes, no attempt has been made to refactor the grammar to restore a look ahead of 1. In addition, in practice the underscores may be purged with a small amount of additional logic in a compiler's scanner as opposed to its parser proper.

Since the leading "0" used to specify an octal literal is itself a digit, underscores are allowed between the leading 0 and subsequent value-carrying digits of an octal literal. This differs from the treatment of the hexadecimal and binary literal specifiers, "0x" and "0b", which are not made up entirely of digit characters of the base in question.

The expert group has discussed limiting underscores between digits to a single underscore rather than the multiple underscores currently allowed. The kernel of the single-underscore grammar would be:

Digits:
DigitsAndUnderscoresopt Digit
DigitsAndUnderscores:
Digit Underscoreopt DigitsAndUnderscoresopt
Underscore:
_

Allowing at most one underscore could prevent some abuses of the feature, at the cost of outlawing some potentially helpful syntactic alignment and introducing a restriction on underscores not present in the use of underscores in identifier names.

Currently the methods in the java.lang package that convert strings to primitive numeric values do not support converting inputs strings with underscores (Oracle bug 6863378). This capability might be added in the future.


Multi-catch and more precise rethrow

Two changes are made to exception handling. First, multiple exception types can be named as being handled by a single catch block. Second, if an exception parameter is not modified and if it is rethrown inside the catch block, the compiler applies a more precise analysis to determine the type of what can be thrown.

To support catching multiple exception types, various specification changes in JLSv3 are needed; first, the grammar of a catch clause of a try statement (JLSv3 §14.20) is extended to allow a series of exception types, separated by the "OR" operator symbol, "|", to be used in the declaration of the exception parameter:

CatchClause:
catch ( FormalParameter CatchFormalParameter ) Block
CatchFormalParameter:
VariableModifiersopt CatchType VariableDeclaratorId
CatchType:
ClassType
ClassType | CatchType
...

A try statement may have catch clauses (also called exception handlers). A catch clause must have exactly one parameter (which is called an exception parameter); the declared type of the exception parameter can be a single class type or can be a union type (denoted with '|') between two or more class types (or alternatives). A catch clause with a union type parameter is called a multi-catch clause. For the purposes of type-checking, a union type D with alternatives D1, D2 ... Dn has type lub(D1, D2 ... Dn) (§15.12.2.7). It is a compile-time error if a union type contains two alternatives Di, Dj where Di is a subtype of Dj.

Each class type used in the declaration of an exception parameter must be the class Throwable or a subclass (not just a subtype) of Throwable, or a compile-time error occurs. In particular, it is a compile-time error if the declared type of the exception parameter is a type variable (§4.4).

...

The notion of finality in JLSv3 §4.12.4 final Variables is expanded to include effectively final:

An exception parameter whose type is a union type is implicitly considered to be final.

In addition, an exception parameter that is not declared final may instead be considered effectively final if it never occurs as the left hand operand of an assignment operator.

If an exception parameter is effectively final, adding the final modifier to its declaration will not introduce any compile time errors. Conversely, an exception parameter that is declared final in a valid program becomes effectively final if the final modifier is removed.

Changing the handling of exception types affects the type system in two ways: in addition to the usual type checking performed on all types, exception types undergo an additional compile time analysis. For the purpose of type checking, an exception parameter declared with a union has type lub(D1, D2, ...) (JLSv3 §15.12.2.7) where the Di are the exception types the catch clause is declared to handle. Informally, the lub (least upper bound) is the most specific supertype of the types in question. In the case of a multi-catch exception parameter, the least upper bound of the types in question always exists since the types of all the caught exceptions must be subclasses of Throwable. Therefore, Throwable is an upper bound of the types in question, but it may not be the least upper bound since some subclass of Throwable may be a superclass (and thereby also a supertype) of the types in question and the exception types in question may implement a common interface. (A lub can be an intersection type of a superclass and one or more interfaces.) For the purpose of exception checking (JLSv3 §11.2), the rules for a throw statement (JLSv3 §11.2.2) are modified:

A throw statement whose thrown expression has static type E can throw E or any subtype of E, or any exception type thrown by the thrown expression. However, when the thrown expression is a final or effectively final (§4.12.4) exception parameter ej of a catch clause Cj, the throw statement instead can throw any exception type T that meets the following conditions:

Informally, if the catch parameter is not modified and if the exception is rethrown, the compiler knows the exception is one of the exceptions throwable by the try block and not already handled by some earlier catch block. This determination of the types that can be thrown can be more precise, meaning more specific than, the declared type of the catch parameter.

Rules are added to JLSv3 §11.2.3 Exception Checking to support exception checking when exception parameters have union types:

...

An instance variable initializer in an anonymous class (§15.9.5) can throw any exception.

For the purposes of exception checking, a try statement declaring one or more catch clauses whose declared type is a union type can be normalized into a try statement declaring a sequence of plain catch clauses without union types. More specifically, the normalization process turns a catch clause whose exception parameter has a declared type of the form D1|D2 ... Dn into a sequence of n plain catch clauses whose exception parameters have types D1, D2, ..., Dn, respectively.


Discussion: Consider the following code:
try { //throws some ReflectiveOperationException }
catch (ClassNotFoundError | IllegalAccessException ex) { //body }
The the purposes of exception checking, above code is semantically equivalent to the following code:
try { //throws some ReflectiveOperationException }
catch (final ClassNotFoundException ex1) { //body }
catch (final IllegalAccessException ex2) { //body }
in which the catch clause with a union type having two alternatives has been normalized into two separately catch clauses, one for each alternative. This normalization process does not introduce any new compile-time errors.

However, note that Java compilers are neither required nor recommended to compile a catch clause with an exception parameter with a union type by duplicating code since it is possible represent this computation in a class file without such duplication.


It is a compile-time error if a catch clause of a normalized try statement catches ...



Discussion: Since it is implicitly final, an explicit final on a multi-catch exception parameter is legal, but discouraged as a matter of style.

There are contrived cases where the more precise exception analysis can stop compilation of currently valid programs (by the compiler identifying more dead code); one example is:

try {
   throw new DaughterOfFoo();
} catch (Foo e) {
   try {
      throw e; // used to throw Foo, now throws DaughterOfFoo
   } catch (SonOfFoo anotherException) { // Reachable?
   }
}

This will compile under source 6 and earlier using the imprecise analysis (the rethrow of e is regarded as being Foo or some subclass of Foo), but will not compile under the more precise analysis since the compiler will correctly view "catch (SonOfFoo ...)" as unreachable. An examination of millions of lines of code in a diverse set of projects, including dozens of members of the Qualitas Corpus and the JDK, found no instances where these conditions occurred. Therefore, using a more precise exception analysis when recompiling existing code is viewed as having acceptable source compatibility risk. If the source can be modified, removing the dead code from the code would resolve the problem.

Fuller support for union types may be added in future releases; forcing union catch parameters to be implicitly or explicitly final preserves flexibility in evolving the language if fuller support is added in the future.

The exception alternatives in a catch clause with a union type must be disjoint, one cannot be a subclass of another. In particular, since a type is a subtype of itself, it is illegal to have duplicated class types in the declaration of an exception parameter. It would be possible to define reasonable semantics when a true superclass/subclass relationship existed between two alternatives, namely to logically remove the subclass from the list of alternatives. While allowing superclass/subclass exceptions would provide source compatibility robustness to changes in exception hierarchies, prohibition of superclass/subclass relationships offers a number of design advantages. First, if deemed helpful, such relationships can be allowed in future releases in a compatible fashion. Since the exceptions types are disjoint, the results of the normalization process to single-type catch clauses are independent of the ordering of the alternatives. (If superclass/subclass relationships were supported, either the subclasses would have to be removed before normalization or a topological sort of the exception types would need to be performed, putting superclasses after subclasses.)

As an implication of the catch clause normalization, each type alternative must be able to catch some exception for the program to be legal. For example, the following statement would causes a compile time error since the use of SonOfFoo is not active:

try {...}
catch(Foo f) {...}
catch(Bar | SonOfFoo e) {....} 

Starting with legal code in a class Client like

try {
  throwAorB();
} catch(ExceptionA | ExceptionB e) {
  ...
}

where ExceptionA and ExceptionB are in a separate library and do not have superclass/subclass relationship when Client is compiled, it is binary compatible with respect to Client for ExceptionA and ExceptionB to have such a relationship when Client is run. This is analogous to other situations where a transformation to library classes that is binary compatible for a client might not be source compatible for the same client.

The revised exception analysis for final and effectively final catch parameters is more precise than the previously defined analysis. Therefore, when the new analysis is applied to existing code, all throws clauses on methods and constructors remain valid.


Improved Type Inference for Generic Instance Creation (diamond)

The diamond language change allows explicit type arguments to constructors of parameterized classes, most notably collections, to be omitted in many situations since the compiler is able to infer the arguments on behalf of the programmer.

First, the grammatical changes to support diamond occur in JLSv3 §15.9 and affect the ClassInstanceCreationExpression production:

ClassInstanceCreationExpression:
new TypeArgumentsopt ClassOrInterfaceType TypeDeclSpecifier TypeArgumentsOrDiamondopt ( ArgumentListopt ) ClassBodyopt
Primary . new TypeArgumentsopt Identifier TypeArgumentsopt TypeArgumentsOrDiamondopt ( ArgumentListopt ) ClassBodyopt
TypeArgumentsOrDiamond:
TypeArguments
< >

Next, the first paragraph of that section is changed:

A class instance creation expression specifies a class to be instantiated, possibly followed by type arguments or diamond "<>" (if the class being instantiated is generic (§8.1.2)), followed by (a possibly empty) list of actual value arguments to the constructor. If the class type argument list is empty — the form "<>" — the class type arguments are to be inferred. It is also possible to pass explicit type arguments to the constructor itself (if it is a generic constructor (§8.8.4)). If the constructor is generic (§8.8.4), the type arguments to the constructor may similarly either be inferred or explicitly passed. In the latter case, these the type arguments immediately follow the keyword new. Inference of class type arguments may influence the constraints on constructor type arguments. Thus, it is a compile-time error if a class instance creation expression provides a constructor type argument list but uses "<>" in place of a class type argument list. It is also a compile-time error if any of the type arguments used in a class instance creation expression are wildcard type arguments (§4.5.1).
Later in that section:
Both unqualified and qualified class instance creation expressions may optionally end with a class body. Such a class instance creation expression declares an anonymous class (§15.9.5) and creates an instance of it. It is a compile-time error if a class instance creation expression declares an anonymous class but uses "<>" in place of a type argument list.

In JLSv3 §15.9.1,

If the class instance creation expression ends in a class body, then the class being instantiated is an anonymous class. Then:

If a class instance creation expression does not declare an anonymous class, then:

In JLSv3 §15.9.3 (Choosing the Constructor and its Arguments),

Let C be the class type being instantiated. To create an instance of C, i, a constructor of C is and type of i are chosen at compile-time by the following rules. First, the actual arguments to the constructor invocation are determined.

Second, a constructor of C and corresponding result type and throws clause are determined. The type of the class instance creation expression is the result type of the chosen constructor, as defined above. Note that the type of the class instance creation expression this type may be an anonymous class type, in which case the constructor being invoked is an anonymous constructor.

Discussion: Syntacticly, ClassOrInterfaceType expands to either a ClassType or InterfaceType (JLSv3 §4.3). Both ClassType and InterfaceType then in turn expand to
TypeDeclSpecifier TypeArgumentsopt
Therefore, "inlining" TypeDeclSpecifier for ClassOrInterfaceType followed by an optional TypeArgumentsOrDiamond captures the desired syntax.

It is legal, but discouraged, to have white space between the "<" and ">" of a diamond.

Raw types have an existing meaning in Java programs and it is useful to maintain a distinction between raw types (hopefully in legacy code) and types inferred by the compiler. Therefore, the diamond syntax is used to mark locations where type inference is requested as opposed to interpreting all instances of raw types as inference sites.

Constructors with explicit type arguments can be assigned to variables having a raw type or a type with a wildcard:


List    rawList  = new ArrayList<Object>(); // Raw types discouraged, but legal
List<?> wildList = new ArrayList<Object>(); 

Consquently, diamond can be used on the left hand side of an assignment where the right hand size uses a raw type or a type with a wildcard:


List    rawList  = new ArrayList<>(); // Raw types strongly discouraged with diamond, but legal
List<?> wildList = new ArrayList<>(); 

In both cases, the compiler infers Object as the value of type argument for the constructor. This result is implied by the rules contained in JLSv3 §15.12.2. Allowing diamond in such locations eases retrofitting existing code to use diamond.

Internally, a Java compiler operates over a richer set of types than those that can be written down explicitly in a Java program. The compiler-internal types which cannot be written in a Java program are called non-denotable types. Non-denotable types can occur as the result of the inference used by diamond. Therefore, using diamond with anonymous inner classes is not supported since doing so in general would require extensions to the class file signature attribute to represent non-denotable types, a de facto JVM change. It is feasible that future platform versions could allow use of diamond when creating an anonymous inner class as long as the inferred type was denotable.


try-with-resources statement

The try-with-resources feature includes a suite of language and library changes to ease management of objects that require an explicit call to a close to free up some underlying resource when the object is no longer in use. Typical objects whose correct management can be assisted by try-with-resources include input streams and output streams where native operating system resources need to be explicitly freed since they are not managed by garbage collection.

The supporting library changes for try-with-resources feature are:

The new interface java.lang.AutoCloseable:

package java.lang;

/**
 * A resource that must be closed when it is no longer needed.
 *
 * @since 1.7
 */
public interface AutoCloseable {
    /**
     * Closes this resource, relinquishing any underlying resources.
     * This method is invoked automatically on objects managed by the
     * {@code try}-with-resources statement.
     *
     * <p>While this interface method is declared to throw {@code
     * Exception}, implementers are strongly encouraged to
     * declare concrete implementations of the {@code close} method to
     * throw more specific exceptions, or to throw no exception at all
     * if the close operation cannot fail.
     *
     * <p>Implementers of this interface are also strongly advised
     * to not have the {@code close} method throw {@link
     * InterruptedException}.
     *
     * This exception interacts with a thread's interrupted status,
     * and runtime misbehavior is likely to occur if an {@code
     * InterruptedException} is {@linkplain Throwable#addSuppressed
     * suppressed}.
     *
     * More generally, if it would cause problems for an
     * exception to be suppressed, the {@code AutoCloseable.close}
     * method should not throw it.
     *
     * <p>Note that unlike the {@link java.io.Closeable#close close}
     * method of {@link java.io.Closeable}, this {@code close} method
     * is not required to be idempotent.  In other words,
     * calling this {@code close} method more than once may have some
     * visible side effect, unlike {@code Closeable.close} which is
     * required to have no effect if called more than once.
     *
     * However, implementers of this interface are strongly encouraged
     * to make their {@code close} methods idempotent.
     *
     * @throws Exception if this resource cannot be closed
     */
    void close() throws Exception;
}

Types directly implementing or extending java.lang.AutoCloseable:

Types newly implementing or extending java.io.Closeable:

One constructor and two new methods are added to java.lang.Throwable to manage suppressed exceptions; in addition, the serial format is updated:

    /**
     * Constructs a new throwable with the specified detail message,
     * cause, {@linkplain #addSuppressed suppression} enabled or
     * disabled, and writable stack trace enabled or disabled.  If
     * suppression is disabled, {@link #getSuppressed} for this object
     * will return a zero-length array and calls to {@link
     * #addSuppressed} that would otherwise append an exception to the
     * suppressed list will have no effect.  If the writable stack
     * trace is false, this constructor will not call {@link
     * #fillInStackTrace()}, a {@code null} will be written to the
     * {@code stackTrace} field, and subsequent calls to {@code
     * fillInStackTrace} and {@link
     * #setStackTrace(StackTraceElement[])} will not set the stack
     * trace.  If the writable stack trace is false, {@link
     * #getStackTrace} will return a zero length array.
     *
     * <p>Note that the other constructors of {@code Throwable} treat
     * suppression as being enabled and the stack trace as being
     * writable.  Subclasses of {@code Throwable} should document any
     * conditions under which suppression is disabled and document
     * conditions under which the stack trace is not writable.
     * Disabling of suppression should only occur in exceptional
     * circumstances where special requirements exist, such as a
     * virtual machine reusing exception objects under low-memory
     * situations. Circumstances where a given exception object is
     * repeatedly caught and rethrown, such as to implement control
     * flow between two sub-systems, is another situation where
     * immutable throwable objects would be appropriate. 
     *
     * @param  message the detail message.
     * @param cause the cause.  (A {@code null} value is permitted,
     * and indicates that the cause is nonexistent or unknown.)
     * @param enableSuppression whether or not suppression is enabled or disabled
     * @param writableStackTrace whether or not the stack trace should be
     *                           writable
     *
     * @see OutOfMemoryError
     * @see NullPointerException
     * @see ArithmeticException
     * @since 1.7
     */
    protected Throwable(String message, Throwable cause,
                        boolean enableSuppression,
                        boolean writableStackTrace)

    /**
     * The list of suppressed exceptions, as returned by {@link
     * #getSuppressed()}.  The list is initialized to a zero-element
     * unmodifiable sentinel list.  When a serialized Throwable is
     * read in, if the {@code suppressedExceptions} field points to a
     * zero-element list, the field is reset to the sentinel value.
     *
     * @serial
     * @since 1.7
     */
    private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL;

    /**
     * Appends the specified exception to the exceptions that were
     * suppressed in order to deliver this exception. This method is
     * thread-safe and typically called (automatically and implicitly)
     * by the {@code try}-with-resources statement.
     *
     * <p>The suppression behavior is enabled unless disabled
     * {@linkplain #Throwable(String, Throwable, boolean) via a
     * constructor}. When suppression is disabled, this method does
     * nothing other than to validate its argument.
     *
     * <p>Note that when one exception {@linkplain
     * #initCause(Throwable) causes} another exception, the first
     * exception is usually caught and then the second exception is
     * thrown in response.  In other words, there is a causal
     * connection between the two exceptions.
     *
     * In contrast, there are situations where two independent
     * exceptions can be thrown in sibling code blocks, in particular
     * in the {@code try} block of a {@code try}-with-resources
     * statement and the compiler-generated {@code finally} block
     * which closes the resource.
     *
     * In these situations, only one of the thrown exceptions can be
     * propagated.  In the {@code try}-with-resources statement, when
     * there are two such exceptions, the exception originating from
     * the {@code try} block is propagated and the exception from the
     * {@code finally} block is added to the list of exceptions
     * suppressed by the exception from the {@code try} block.  As an
     * exception unwinds the stack, it can accumulate multiple
     * suppressed exceptions.
     *
     * <p>An exception may have suppressed exceptions while also being
     * caused by another exception.  Whether or not an exception has a
     * cause is semantically known at the time of its creation, unlike
     * whether or not an exception will suppress other exceptions
     * which is typically only determined after an exception is
     * thrown.
     *
     * <p>Note that programmer written code is also able to take
     * advantage of calling this method in situations where there are
     * multiple sibling exceptions and only one can be propagated.
     *
     * @param exception the exception to be added to the list of
     *        suppressed exceptions
     * @throws IllegalArgumentException if {@code exception} is this
     *         throwable; a throwable cannot suppress itself.
     * @throws NullPointerException if {@code exception} is {@code null}
     * @since 1.7
     */
    public final void addSuppressed(Throwable exception)

    /**
     * Returns an array containing all of the exceptions that were
     * suppressed, typically by the {@code try}-with-resources
     * statement, in order to deliver this exception.
     *
     * If no exceptions were suppressed or {@linkplain
     * Throwable(String, Throwable, boolean) suppression is disabled},
     * an empty array is returned. This method is
     * thread-safe. Writes to the returned array do not affect future
     * calls to this method.
     *
     * @return an array containing all of the exceptions that were
     *         suppressed to deliver this exception.
     * @since 1.7
     */
    public final Throwable[] getSuppressed()

    // Added explicit specification for readObject.
    /**
     * Reads a {@code Throwable} from a stream, enforcing
     * well-formedness constraints on fields.  Null entries and
     * self-pointers are not allowed in the list of {@code
     * suppressedExceptions}.  Null entries are not allowed for stack
     * trace elements.
     *
     * Note that there are no constraints on the value the {@code
     * cause} field can hold; both {@code null} and {@code this} are
     * valid values for the field.
     */
    private void readObject(ObjectInputStream s)


    /**
     * Write a {@code Throwable} object to a stream.
     *
     * A {@code null} stack trace field is represented in the serial
     * form as a one-element array whose element is equal to {@code
     * new StackTraceElement("", "", null, Integer.MIN_VALUE)}.
     */
    private void writeObject(ObjectOutputStream s)

   /**
     * The stack trace, as returned by {@link #getStackTrace()}.
     * The field is initialized to a zero-length array. A {@code
     * null} value of this field indicates subsequent calls to {@link
     * #setStackTrace(StackTraceElement[])} and {@link
     * #fillInStackTrace()} will be be no-ops.
     *
     * @serial
     * @since 1.4
    private StackTraceElement[] stackTrace;

Three Throwable subclasses in java.lang have a disclaimer added that their objects may be constructed by the virtual machine as if suppression were disabled:


The language specification changes involve §14.20 "The try statement," and will eventually introduce a new subsection §14.20.3 "Execution of try-with-resources," although the specification presented below is not partitioned as such.


SYNTAX: The existing set of grammar productions for TryStatement in §14.20 is augmented with an alternative including resources:

TryStatement:
try Block Catches
try Block Catchesopt Finally
try ResourceSpecification Block Catchesopt Finallyopt

Supporting new grammar productions are added:

ResourceSpecification:
( Resources ;opt )
Resources:
Resource
Resource ; Resources
Resource:
VariableModifiersopt Type VariableDeclaratorId = Expression

A try-with-resources statement has a resource specification that declares resources to be automatically closed at the end of the Block. A resource specification declares one or more local variables; the type of each variable must be a subtype of AutoCloseable or a compile-time error occurs. A variable must not have the same name as a variable declared earlier in the resource specification, a local variable, or parameter of the method or initializer block immediately enclosing the try statement, or a compile-time error occurs.

The scope of a variable declared in a resource specification of a try-with-resources statement (§14.20) is from the declaration rightward over the remainder of the resource specification and the entire Block associated with the try. Within the Block of the try, the name of the variable may not be redeclared as a local variable of the directly enclosing method or initializer block, nor may it be redeclared as an exception parameter of a catch clause in a try statement of the directly enclosing method or initializer block, nor may it be redeclared as a variable in the resource specification, or a compile-time error occurs. However, a variable declared in a resource specification may be shadowed (§6.3.1) anywhere inside a class declaration nested within the Block of the try.

The meaning of a try-with-resources statement with a Catches clause or Finally block is given by translation to a try-with-resources statement with neither a Catches clause nor a Finally block:

try ResourceSpecification
  Block
Catchesopt
Finallyopt

try {
  try ResourceSpecification
    Block
}
Catchesopt
Finallyopt

After translation outward of any Catches clause or Finally block to an outer try, in a try-with-resources statement with no Catches clause or Finally block that manages a single resource:

In a try-with-resources statement that manages multiple resources:

The exceptions that can be thrown by a try-with-resources statement are the exceptions that can be thrown by the Block of the try-with-resources statement plus the union of the exceptions that can be thrown by the automatic closing of the resources themselves. Regardless of the number of resources managed by a try-with-resources statement, it is possible for a Catches clause associated with the statement to catch an exception due to initialization or automatic closing of any resource.

A try-with-resources statement with a ResourceSpecification clause that declares multiple Resources is treated as if it were multiple try-with-resources statements, each of which has a ResourceSpecification clause that declares a single Resource. When a try-with-resources statement with n Resources (n > 1) is translated, the result is a try-with-resources statement with n-1 Resources. After n such translations, there are n nested try-catch-finally statements, and the overall translation is complete.

The meaning of a try-with-resources statement with a ResourceSpecification clause and no Catches clause or Finally block is given by translation to a local variable declaration and a try-catch-finally statement. During translation, if the ResourceSpecification clause declares one Resource, then the try-catch-finally statement is not a try-with-resources statement, and ResourceSpecificationtail is empty. If the ResourceSpecification clause declares n > 1 Resources, then the try-catch-finally statement is treated as if it were a try-with-resources-catch-finally statement, where ResourceSpecificationtail is a ResourceSpecification consisting of the 2nd, 3rd, ..., nth Resources in order. The translation is as follows, where the identifiers #primaryException, #t, and #suppressedException are fresh:

try ResourceSpecification
  Block

{
  final VariableModifiers_minus_final R #resource = Expression;
  Throwable #primaryException = null;

  try ResourceSpecificationtail
    Block
  catch (Throwable #t) {
    #primaryException = t;
    throw #t;
  } finally {
    if (#resource != null) {
      if (#primaryException != null) {
        try {
          #resource.close();
        } catch(Throwable #suppressedException) {
          #primaryException.addSuppressed(#suppressedException);
        }
      } else {
        #resource.close();
      }
    }
  }
}

The value of VariableModifiers_minus_final is the set of modifiers on the variable (except for final, if present); R is the type of the variable declaration; and #resource is the name of the variable declared in the Resource.

The close method is only called on a resource if the resource is initialized to a non-null value.

The reachability and definite assignment rules for the try statement with a resource specification are implicitly specified by the translations above.


Discussion: The Throwable.printStackTrace family of methods have their expected behavior updated to include displaying information about suppressed exceptions.

An implication of the combined grammar is that a try statement must have at least one of a catch clause, a finally block, and a resource specification. Furthermore, it is permissible for a try statement to have exactly one of these three components.

The grammar for a declared resource is
VariableModifiersopt Type VariableDeclaratorId = Expression
rather than the simpler LocalVariableDeclaration
to disallow code like
AutoCloseable a, b, c
which is not useful in this context since the variables have to be initialized. A suggested grammatical extension has been to allow multiple resources to share the declared resource type as in

// Suggested syntax extension
try(Resource r0 = new Resource(), // Comma separating resources
    r1 = new Resource()) {        // with a shared type
    //...
}

However, this has been judged to be a change with low utility since managing multiple resource of the same type is expected to be relatively uncommon. In many cases where multiple resources are managed, one resource is a wrapper around an underlying resource.

The exception behavior of close methods is accounted for in determining the set of exceptions a try-with-resources statement can throw.

By design, no special accommodations are made to deal with the ThreadDeath error which is spawned by the long-deprecated Thead.stop method.

Resource declarations in a resource specification are implicitly final. For consistency with existing declarations that have implicit modifiers, it is legal (though discouraged) for a programmer to provide an explicit "final" modifier. By allowing non-final modifiers, annotations such as @SuppressWarnings will be preserved on the translated code, which implies @SuppressWarnings on a resource will have the intended effect.

Unlike the fresh identifier in the translation of the enhanced-for statement, the #resource variable is in scope in the Block of a try-with-resources statement.

The translation exploits the improved precision of exception analysis for an effectively final exception parameter.

At least in Java SE 7, a class must have a method named "close" to implement the AutoCloseable interface and thus work with the try-with-resources statement. To allow methods with other names like "dispose" to be called at block exit instead, an adapter interface with a matching factory can be used to wrap the object in question and forward calls from "close" to the type-specific clean-up method. In the future, it is possible other mechanisms, such as interface injection, may also allow classes not declared to implement AutoCloseable to be operated on by the try-with-resources statement


Simplified Varargs Method Invocation

JLSv3 mandates many uninformative unchecked warning messages be generated by compilers when certain potentially problematic varargs methods are called. The set of methods considered problematic in this way includes methods in the core JDK libraries. This feature generates a new warning at the declaration of such methods and provides a mechanism for the programmer to state the method is actually not problematic so that warnings are not generated at either the method's declaration or use.

As part of this language change, an unchecked warning is required at declaration sites of varargs methods and constructors that have a non-reifiable element type (JLSv3 §4.7) for the varargs parameter. Previously, call sites of such methods have generated unchecked warnings. The requirement is specified by adding a sentence to JLSv3 §8.4.1 "Formal Parameters":

If the last formal parameter is a variable arity parameter of type T, it is considered to define a formal parameter of type T[]. The method is then a variable arity method. Otherwise, it is a fixed arity method. If T is a non-reifiable type (§4.7), then the declaration of the variable arity method generates a compile-time unchecked warning (§4.12.2.1) unless the unchecked warning is suppressed by the method being annotated with a @SafeVarargs annotation (reference to new subsection in §9.6.1). Invocations of a variable arity method may contain more actual argument expressions than formal parameters. All the actual argument expressions that do not correspond to the formal parameters preceding the variable arity parameter will be evaluated and the results stored into an array that will be passed to the method invocation (§15.12.4.2).

A new subsection is added to the Predefined Annotation Types section of JLSv3, (§9.6.1), to describe SafeVarargs:

SafeVarargs

A variable arity parameter with a non-reifiable element type (§4.7) can cause heap pollution (§4.12.2.1) and associated unchecked warnings. Such warnings are uninformative if the body of the variable arity method is well-behaved with respect to the variable arity parameter. The annotation type SafeVarargs, when used to annotate a method or constructor, makes a programmer assertion which prevents the compiler from reporting unchecked warnings for the declaration or invocations of a variable arity method or constructor where the compiler would otherwise do so due to the variable arity parameter having a non-reifiable element type.

It is a compile-time error if a fixed-arity method or constructor is annotated with the @SafeVarargs annotation. It is a compile-time error if a variable-arity method that is neither static nor final is annotated with the @SafeVarargs annotation.

The documentation of the new SafeVarargs annotation type is below.


Annotation Type SafeVarargs



@Documented
@Retention(value=RUNTIME)
@Target(value={CONSTRUCTOR,METHOD})
public @interface SafeVarargs

A programmer assertion that the body of the annotated method or constructor does not perform potentially unsafe operations on its varargs parameter. Applying this annotation to a method or constructor suppresses unchecked warnings about a non-reifiable variable-arity (vararg) type and suppresses unchecked warnings about parameterized array creation at call sites.

In addition to the usage restrictions imposed by its @Target meta-annotation, compilers are required to implement additional usage restrictions on this annotation type; it is a compile-time error if a method or constructor declaration is annotated with a @SafeVarargs annotation, and either:

Compilers are encouraged to issue warnings when this annotation type is applied to a method or constructor declaration where:


The platform methods and constructors annotated with a @SafeVarargs annotation are:


Discussion: The non-local effect of a @SafeVarags annotation suppressing warnings at call sites (in addition to the declaration site) differs from the effects of a @SuppressWarnings annotation on a declaration.

The canonical target for a @SafeVarargs annotation is a method like java.util.Collections.addAll, whose declaration starts with


public static <T> boolean java.util.Collections.addAll(Collection<? super T> c, T... elements)

The varargs parameter has underlying type T[], which is non-reifiable. However, the method fundamentally just reads from the input array and adds the elements to a collection, which is a safe operation with respect to the array. Therefore the unchecked warnings at call sites of Collections.addAll are arguably spurious and uninformative. Applying a @SafeVarargs annotation to the method stops generation of these unchecked warnings at the methods' call sites.

In practice, the EnumSet.of method should not generate unchecked warnings since the inferred type in any given application of the method should be some particular concrete enum type. This is a consequence of the additional restrictions imposed on enum types, such as they are all direct subclasses of the abstract class java.lang.Enum. However, adding @SafeVarargs does correctly capture the semantics of the method.

Generally safe operations on the varargs parameter include only reading from the parameter and treating the parameter in an invariant sense. Aliasing the parameter is potentially unsafe.

Since new unchecked warnings are being introduced, those diligently compiling with options like "-Xlint:unchecked -Werror" will see a build error under JDK 7 if any of the suspicious varargs method declarations are found. To address this, the @SafeVarargs annotation can be applied to the declarations, if appropriate, or in the compiler reference implementation the @SuppressWarnings({"unchecked", "varargs"}) annotation can be applied. Unlike @SafeVarargs, the @SuppressWarnings annotation will not squelch unchecked warnings at the call sites of the annotated method.

Since a @SafeVarargs annotation is only applicable to static methods, final instance methods, and constructors, the annotation is not usable in a situation where method overriding occurs. Annotation inheritance only works on classes (not methods, interfaces, or constructors) so without changing annotation inheritance, a SafeVarargs-style annotation cannot be passed through general instance methods in classes or through interfaces.

Since it affects programming language semantics, the SafeVarargs annotation type is placed in the java.lang package.

The SafeVarargs annotation type is declared with a runtime RetentionPolicy for several reasons. Some representation of the SafeVarargs status is needed in class files to allow compilers to know to omit unchecked warnings at call sites of annotated methods, unchecked warnings that would otherwise be mandated by the language specification. If this information is stored using an annotation, the annotation type can have one of three retention policies, SOURCE, CLASS, or RUNTIME. With the SOURCE policy, the annotation would not be stored in the class file at all, which would not meet the requirements of eliding warnings when uses of the annotated method or constructor are compiled separately from the class declaring the method or constructor. That leaves CLASS and RUNTIME as potential retention policies. Both policies use equal space in the class file. However, an advantage of RUNTIME retention is that no explicit method is needed in reflective APIs to query the SafeVarargs status of a method or constructor since the presence or absence of the annotation can be tested. For example, there is no need for an isSafeVarargs method on the Method and Constructor classes in the java.lang.reflect package or for an isSafeVarargs method in javax.lang.model.element.ExecutableElement. Therefore, the SafeVarargs annotation type is declared with RUNTIME retention and no methods are added to any of the platform's reflective APIs to query for this information. This information could conceivably be stored in a new class file attribute, but small language changes do not change the VM specification and a new recognized class file attribute is a VM change. An additional benefit of having the information in class files is enabling class file-based analysis tools to perform additional checks on the operations of annotated methods and constructors.


Changelog

Changes since v0.83

Appendix — JSR 269 language model

The JSR 269 language model follows somewhat different evolution rules than most APIs included in Java SE. In particular, while the changes to the API are binary compatible, certain source incompatible changes are made of necessity. In particular, methods have been added to the visitor interfaces to allow operations on newly-added language constructs to be performed. This evolution path was expected during JSR 269's development and for that reason, developers were warned to not directly implement the visitor interfaces, but rather to extend one of the visitor utility classes. The utility classes are versioned per release and implement default behavior appropriate for that release.

Changes to the language model include:


Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.