Alex Buckley
Table of Contents
Integration of modules in The Java Language Specification, Java SE 9 Edition ("JLS9") is summarized as follows:
Modules are motivated at a high level in 1.1 "Organization of the Specification", and in the introduction to Chapter 7 "Packages and Modules" (renamed from "Packages").
A new section, 7.7 "Module Declarations", specifies the syntax and semantics of named modules. Unnamed modules are specified in 7.7.5, and marginally affect the specification of unnamed packages in 7.4.2.
The binary form of a module declaration is specified in 13.1, and is largely reliant on 7.7.
The "restricted keywords" used in module declarations are introduced in 3.9.
Module names are introduced in 6.5 and 6.5.1. Non-normative advice on modules names is given in 6.1.
However, the name of a reference type in 6.7 and 13.1 does not include the name of the module in which the type was declared (that is, the name of the module with which the compilation unit that contained the type declaration is associated). Therefore, since two modules might contain types with the same binary name, 4.3.4 and 7.6 distinguishes two reference types on the basis of module name and binary name. Two types with binary name P.C are distinct if declared in (compilation units associated with) different modules.
Historically, 7.2 and 7.3 defined the concept of a universe of
"observable" compilation units, but left their discovery up to a
compiler. This remains the case in JLS9, because a specification
cannot disprove a compiler's claim that a particular compilation
unit in a particular directory does not exist. However, in JLS9, if
a compiler does choose to observe an ordinary compilation unit, and does
choose to associate it with a modular
compilation unit, then the compiler must respect
requires
directives in the modular
compilation unit when determining the meaning of types referenced
from the ordinary compilation unit.
In particular, the compiler must build a universe of "visible" compilation units on a per-module basis when processing ordinary compilation units that it has observed. (The traditional definition of "visible" in 6.4.1 to mean "in scope and not shadowed" has been removed, and the uses in 6.3, 6.4.2, 6.5.5, 6.5.6, 6.5.7, and 15.12.1 have been modified accordingly.)
Under these rules, it is possible for a given ordinary compilation unit to have "visibility" of ordinary compilation units in a package of another module, even though that package is not exported by its module. The types declared in the ordinary compilation units of that package will nevertheless be inaccessible to code in the given ordinary compilation unit.
Moreover, under these rules, it is possible for a given ordinary compilation unit to have "visibility" of ordinary compilation units which declare the same package in different modules. That is, the same package may be visible in multiple modules, irrespective of what those modules export. However, the rules of module resolution ensure that a given module enjoys "readability" to no more than one module which exports a package of a given name. The constrained model of "readability" is more helpful when determining the meaning of a package or type name than the less constrained model of "visibility". Accordingly, 7.4.3 introduces the concept of "uniquely visible" to help choose which visible ordinary compilation unit is in play when a package name or type name is given meaning.
The following sections are changed by the overlaying of module membership and dependencies on the universe of compilation units:
6.1, 6.3, 6.5.3, 6.5.3.1, 6.5.3.2, 6.5.5.1, 6.5.5.2, 7.5.2
Accessibility is defined in 6.6.1. In JLS9, this section
distinguishes exported public
types
(those in packages exported by their module) from unexported
public
types (those in packages not
exported by their module). In effect, JLS9 defines a new level in
the type accessibility hierarchy. There are corresponding minor
edits to 6.6.2 and 6.6.2.1 for protected
types.
The 6.6.1 definition is referenced widely from Chapter 8 and later. Despite accessibility being a 2-arity function (both accessor and accessee matter), many rules refer to an "accessible" type without specifying the accessor explicitly. For example, 8.1.4 specifies that when class C extends B, B must be an accessible class type; the reader was assumed to understand that B must be accessible from the point of view of C. In JLS9, the reader is still assumed to understand who is the accessor as well as the accessee, but now the accessor's module is as important as the accessor's type.
The following sections are semantically unchanged by the introduction of the new type accessibility level:
(Sections marked with a
historically referred to 6.6.1, so JLS9 "automatically" prevents
the use sites described by these sections from accessing unexported
public
types of another module, just
as JLS8 prevented them from accessing package access types of
another package.)
(Sections marked with p
make
explicit mention of public
(and
sometimes protected
) without
necessarily meaning that a type should be accessible; these
sections are occasionally clarified to speak about an accessible
type instead.)
7.5a, 7.5.1a, 7.5.3a, 7.5.4a, 7.6p 8.1.1a, 8.1.4a, 8.1.5a, 8.2p, 8.3a, 8.4.8p, 8.4.8.1p, 8.4.8.2, 8.4.8.3p 8.5a, 8.8a, 8.8.3a, 8.8.7.1a, 8.8.10p, 8.9.1a, 8.9.2p, 8.9.3p 9.1.1p, 9.1.3a, 9.2p, 9.3p, 9.4p, 9.4.1a, 9.5p, 9.6.1p, 9.6.4.4p, 9.7.1a, 9.8p 10.7p 12.1.4p 12.3.3p 15.8.2a, 15.9.1a, 15.9.3a, 15.9.5.1a, 15.11.1a, 15.11.2a 15.12.2a, 15.12.2.1a, 15.12.2.5a, 15.12.2.6a, 15.12.3a, 15.12.4.3p 15.13a, 15.13.1a, 15.13.2a, 15.27.3a
Note 1. There are no changes to member accessibility in 6.6.1.
The first reason is that a member's declaring type still dominates
access when used as the qualifying type. The second reason, which
is more substantive, is that a member may be inherited across a
module boundary and then accessed via a qualifying type in the
other module. This also explains why inheritance of a class's or
interface's public
method is unchanged
in 8.4.8 and 9.4.1.1; a public
method
continues to be inherited across a module boundary even when the
method's declaring public
type is not
accessible outside the module. More broadly, public
and protected
members (including types, per 8.2, and methods, per 8.4.8) are
inherited by a subclass in a different module; the usual
inter-package rules that apply for access to a protected
member still apply when inter-package is
also inter-module.
Note 2. 8.4.8.3 specifies the "no shrinkage of access when overriding or hiding" rule. Because the rule is specified in terms of the access modifiers of the overridden and overriding methods, rather than their accessibility, there is no change in JLS9. On the other hand, 8.8.9 said "The default constructor has the same accessibility as the class."; in JLS9, this is changed to refer to access modifiers instead, since the 6.6.1 rules for accessibility of a constructor are specified in terms of access modifiers.
Annotations on module declarations cause minor additions to 9.6.4.1, 9.6.4.6, and 9.7.4, as well as 7.5.1 and 7.5.3.
Observations on the binary compatibility of changing a module declaration are given in 13.3.
Integration of modules in The Java Virtual Machine Specification, Java SE 9 Edition ("JVMS9") is summarized as follows:
The binary form of a module declaration is specified in 4.1 and in a new section 4.7.25 "The Module Attribute".
Module names referenced by a module declaration are described in 4.2.3, and stored in a new kind of constant pool structure specified in 4.4.11 "The CONSTANT_Module_info Structure". Package names referenced by a module declaration are also described in 4.2.3, and stored in a new kind of constant pool structure specified in 4.4.12 "The CONSTANT_Package_info Structure".
Compilation from module-info.java
to module-info.class
is discussed in
3.16.
Auxiliary attributes employed after compilation to define the content of a module are specified in 4.7.26 "The ModulePackages Attribute" and 4.7.27 "The ModuleMainClass Attribute".
5.3.6 "Modules and Layers" is a new section that describes the relationship of classes and class loaders to modules and layers.
Accessibility is specified in 5.4.4. In JVMS9, this section
(like the corresponding section 6.6.1 in JLS9) distinguishes
exported public
types (those in
run-time packages exported by their run-time module) from
unexported public
types (those in
run-time packages not exported by their run-time module).
Prior to Java SE 9, it was possible to change the accessibility of a type's member for a specific reflective object in the Java SE Platform API, but this was orthogonal to the accessibility of a type's member resolved via the constant pool. In Java SE 9, it is possible to change the accessibility of a type itself, even when resolved via the constant pool, by using the Java SE Platform API to export a package from a run-time module. While 5.4.4 does respect this increase in a type's accessibility, 5.4.3 clarifies that dynamically exporting a package in this way does not change the accessibility of a previously inaccessible type.