Project Jigsaw: Language changes for Modules

2009/2/3

Definitions

A module is a set of types in one or more named packages.

The members of a module are all the class and interface types declared in all the compilation units of the module.

A module identity is a structure M@V, where M is the name of the module and V is the version of the module. The Java language assigns no meaning to the version of a module.

A module compilation unit is a source file named module-info.java.

A package compilation unit is a source file named package-info.java.

Language syntax

Example

import P.*;
@Foo
module M1@1.0 provides M2@2.0, M3@3.0 {
  requires M4@4.0, M5@5.0;
  permits  M6;
} 

Grammar

CompilationUnit:
  ImportDeclarations_opt ModuleDeclaration_opt PackageDeclaration_opt ImportDeclarations_opt TypeDeclarations_opt

ModuleDeclaration:
  Annotations_opt 'module' RestOfModuleDeclaration

RestOfModuleDeclaration:
  QualifiedIdentifier ';'
  ModuleId ModuleProvides_opt '{' { ModuleMetadata } '}'

ModuleProvides:
  'provides' ModuleId {',' ModuleId}_opt

ModuleMetadata:
  ModuleRequires
  ModulePermits

ModuleRequires:
  'requires' {ModuleRequiresModifier}_opt ModuleId {',' ModuleId}_opt ';'

ModuleRequiresModifier:
  'optional'
  'private'
  'local'

ModulePermits:
 'permits' QualifiedIdentifier {',' QualifiedIdentifier}_opt ';'

ModuleId:
  QualifiedIdentifier ModuleVersion_opt

ModuleVersion:
  '@' Space_opt ModuleVersionStart ModuleVersionPart*
  '@' Space_opt StringLiteral

ModuleVersionStart:
  digit
  '['
  '('

ModuleVersionPart:
  InputCharacter but not FF, Space, Tab, '"', '\'', '\\', ',', ';'
  // InputCharacter is any UnicodeInputCharacter except CR and LF

Modifier:
  Annotation
  'public'
  'module'
  'protected'
  'private'
  'static'
  ...

Language semantics

Module membership

A module declaration in a compilation unit specifies the name of the module to which types in the compilation unit belong:

module M;
package P;
public class Foo {...}
module is a restricted keyword in the ModuleMembership and MethodOrFieldDecl productions of a CompilationUnit.

(A restricted keyword is a character sequence that is an identifier except where it appears as a terminal in a specific production, whereupon the terminal itself is defined as a keyword. Restricted keywords permit character sequences that were formerly classified as identifiers to be introduced into the syntactic grammar of the Java programming language as if they are keywords in very limited contexts. This overcomes the problem that introducing keywords into the syntactic grammar otherwise makes identifiers with the same character sequences illegal. There must be no ambiguity between a restricted keyword and an identifier anywhere in the grammar.)

A module name can be simple or qualified. There is no obscuring between module names and other names. This means there is no prohibition against a module having the same name as any package.

If a compilation unit declared in package P does not contain a module declaration, then the compilation unit belongs to the module declared in the package compilation unit for P, or to the unnamed module if either no such package compilation unit exists or it exists without a module declaration. All types declared in the compilation unit are members of the module to which the compilation unit belongs.

For example, a compilation unit:

com/foo/bar/C.java

which does not contain a module declaration will have its types be members of the module com.foo.bar iff com/foo/bar/package-info.java exists and declares the com.foo.bar module; or a member of the unnamed module otherwise.

If none of the observable compilation units in a package (including the package compilation unit) contain a module declaration, then the host system may optionally treat all the compilation units as if they contained declarations of a module known to the host system.

This allows a Java compiler invoked from the command line to support parameters which associate a package with a module, even if no compilation units in the package contain a module declaration.

Note that a type is a member of the unnamed module if it is a) declared in a compilation unit with a package declaration but no module declaration, and b) the relevant package compilation unit (if it exists) has no module declaration.

A type in an unnamed package is a member of the unnamed module. It is a compile-time error if a compilation unit in an unnamed package belongs to a named module.

The host system must enforce the restriction that it is a compile-time error if an observable compilation unit C belongs to a module which is not consistent with either:

The host system may choose to enforce the restriction that it is a compile-time error if an observable compilation unit belongs to a module which is not consistent with the module of any other observable compilation unit in the same package.

Comment: All explicit module declarations in the observable compilation units for a package should be consistent, but we do not want to require a compiler to check consistency across every observable compilation unit every time one is re-compiled.

Module accessibility

If a class or interface type is declared public, then it may be accessed by any code, provided that the compilation unit in which it is declared is observable.

If a class or interface type is declared module, then it may be accessed only from within the module in which it is declared.

If a top level class or interface type is not declared public or module, then it may be accessed only from within the package in which it is declared.

A member (class, interface, field, or method) of a reference (class, interface, or array) type or a constructor of a class type is accessible only if the type is accessible and the member or constructor is declared to permit access: - If the member or constructor is declared public, then access is permitted. - If the member or constructor is declared module, then access is permitted only from within the module containing the class in which the module member or constructor is declared.

Module annotations

Annotations may be used on module declarations, with the restriction that at most one annotated module declaration is permitted for a given module. The sole annotated module declaration, if it exists, is placed in a compilation unit known as the module compilation unit. When packages are stored on a filesystem, the module compilation unit is a file called module-info.java. This file should be stored in a directory corresponding to the module name.

The restricted keyword module in a module declaration in a module compilation unit may optionally be preceded by annotation modifiers. If an annotation a on a module declaration corresponds to an annotation type T, and T has a (meta-)annotation m that corresponds to annotation.Target, then m must have an element whose value is java.lang.annotation.ElementType.MODULE, or a compile-time error occurs.

The host system must compile a non-empty module compilation unit if it contains at least a module declaration. It is a compile-time error if a module compilation unit does not contain a module declaration, or if it contains at least one type declaration without a package declaration.

Module metadata

The module declaration in a module compilation unit may contain metadata that expresses the dependencies of the module and any aliases by which the module is known:

module M provides P {
  requires N;
  permits  L;
}

In M's metadata, requires N denotes a dependency of module M on module N. permits L denotes that module L may have a dependency on module M, and that no other module is permitted to have a dependency on module M. If a module does not have any permits clauses in its metadata, then any module may have a dependency on it.

A module name may appear as an operand in at most one requires clause and at most one permits clause of a module compilation unit.

All public types in a module are observable to all types in the module. The host system must use a module's dependencies to determine which public types not in the module are observable to the types in the module. If public type T is not in module M, then T is observable to any type in M if:

A module M re-exports a type T if:

If a type T belongs to module M and is also observable from a module on which M has a dependency, then the Java programming language imposes no preference on which T should be used. However, the host system should choose which T to make observable in M and use it consistently.

The Java programming language imposes no ordering on the dependencies denoted in M's metadata. If M has a dependency on N which contains T, and M also has a dependency on O which re-exports T, then the host system is responsible for choosing either N or O as the module which makes T observable to M.

The optional modifier on a dependency indicates that the host system must not give an error if it attempts to use the module whose name appears in the dependency.

The local modifier on a normal dependency indicates to the host system that the target module of the dependency must have its types loaded with the same defining classloader as types in the module with the dependency. If local is not present, then the host system may choose an arbitrary defining classloader for types of the target module.

The clause provides P indicates that a dependency on module P by some other module may be satisfied by module M.