Modules in the Java Language and VM (Obsolete)


Chapter 1. Language changes

1.1. Example

module M @ 1.0 {
  requires A @ /* Use v2 or above */ >= 2.0 ;
  requires B for compilation, reflection;

  requires service S1;
  requires optional service S2;

  provides MI @ 4.0;
  provides service MS with C;
  exports  ME;
  permits  MF;
  class    MMain;

  view N {
    provides NI @ 1.0;
    provides service NS with D;
    exports  NE;
    permits  MF;
    class    NMain;
  }
}

1.2. Rules

module, requires, compilation, reflection, execution, service, local, optional, provides, with, exports, permits, and view are restricted keywords.

This means that 'provides service ;' is legal - service is interpreted as an identifier because the token stream can be seen as not proceeding to declare a service. Also, 'provides service service with service ;' is legal.

About a module declaration:

  • A compilation unit (JLS 7.3) may contain a module declaration.

    In this case, the filename of the compilation unit is typically module-info.java.

  • A module declaration indicates a module name, optionally followed by @ and a module version. A module declaration may not be annotated.

  • A module name is a qualified identifier, in the spirit of a package-or-type name and a type name (JLS 6.5).

  • A module version is a new kind of literal, starting with a digit and thereafter consisting of Java letters, Java digits, . characters, and - characters in a sequence acceptable to the module system. (Requirement)

  • If a module declaration does not express a dependency on the java.base module, and the module declaration is not of java.base itself, then it is as if the module declaration has a dependency on a version of the java.base module chosen by the host system.

About the requires directive:

  • requires takes a qualified identifier indicating a module name (if the modifier service is not present) or a service name (if the modifier service is present). (Requirement, Requirement)

  • A module name may be preceded by one or more of the flags local and public.

    A module name may be followed by @ and a version query. A version query is either a version, or an operator followed by a version. (Requirement)

    A module name (or version query) may be followed by for and one or more of the scopes compilation, reflection, and execution. (Requirement, Description of scopes)

    If no for clause is present, then it is as if a for compilation, execution clause was present.

  • A service name may be preceded by an optional flag.

About the other directives:

  • provides takes a qualified identifier indicating a module name to serve as an alias (if the modifier service is not present) or a service name to be implemented (if the modifier service is present). (Requirement)

    A module name may be followed by @ and a version.

    A service name must be followed by a with clause that indicates the implementation for the service. (Requirement)

  • exports takes a qualified identifier indicating the name of a package to be exported. (Requirement)

  • permits takes a qualified identifier indicating the name of a module which is permitted to depend on this module. (Requirement)

  • class takes a qualified identifier indicating the name of the type which is an entry point for the module or view.

  • view takes a qualified identifier indicating the name of the view, followed by a set of provides, exports, permits, and class clauses defining the view as seen by requires clauses in other modules.

  • Every module has a default view. Any provides, exports, permits, or class clause not declared in a named view is implicitly declared in the module's default view.

Compile-time errors concerning duplicates:

  • It is a compile-time error if more than one requires clause (that gives a module name) in a module declaration indicates the same module name.

  • It is a compile-time error if more than one requires service clause in a module declaration indicates the same service name.

  • It is a compile-time error if more than one provides clause (that gives a module name) in a view indicates the same module name.

    It is a compile-time error if more than one provides service clause in a view indicates the same pair of service name and implementation.

    (Multiple provides service clauses in a view may give the same service name with different implementations.)

  • It is a compile-time error if more than one exports clause in a view indicates the same package name.

  • It is a compile-time error if more than one permits clause in a view indicates the same module name.

  • It is a compile-time error if a module declaration contains more than one view of the same name (whether declared as a non-default view or implicit as the default view).

  • It is a compile-time error if an exports clause in a non-default view indicates the same package name as an exports clause in the default view.

    (A non-default view inherits the exports clauses of the default view, so duplicates should be prohibited among the combined default/non-default exports, as well as among the non-default exports.)

Compile-time errors concerning references to other entities:

  • It is a compile-time error if an implementation named by the with clause of provides service is abstract, or is not public, or does not have a public no-args constructor, or is an inner class (JLS 8.1.3).

  • A type named as an entry point must indicate a class (of any accessibility) that declares a method called main which is public, static, void, and has a single formal parameter of type String[], or a compile-time error occurs.

  • The operator in a version query must be <<, <=, =, >=, or >>, or a compile-time error occurs.

  • It is a compile-time error if a requires clause indicates both the reflection scope and the execution scope.

1.3. Grammar

The grammar below uses the following BNF-style conventions:

  • [x] denotes zero or one occurrences of x.

  • {x} denotes zero or more occurrences of x.

  • (x | y) means one of either x or y.

1.3.1. Lexical grammar


Literal:
  VersionLiteral

VersionLiteral:
  JavaDigit VersionLiteralChars

VersionLiteralChars:
  VersionLiteralChar
  VersionLiteralChars VersionLiteralChar

VersionLiteralChar:
  JavaLetterOrDigit
  .
  -

1.3.2. Syntactic grammar


CompilationUnit:
  [PackageDeclaration] {ImportDeclaration} {TypeDeclaration}
  [ModuleDeclaration]

ModuleDeclaration:
  module ModuleNameAndVersion { {ModuleDirective} }

ModuleNameAndVersion:
  ModuleName [@ VersionLiteral]

ModuleName:
  Identifier
  ModuleName . Identifier


ModuleDirective:
  RequiresDirective
  ProvidesDirective
  ExportsDirective
  PermitsDirective
  EntrypointDirective
  ViewDeclaration

RequiresDirective:
  requires {local | public} ModuleNameAndVersionQuery [for ScopeList] ;
  requires [optionalservice ServiceName ;

ModuleNameAndVersionQuery:
   ModuleName [@ VersionQuery]

VersionQuery:
  [Operator] VersionLiteral

ScopeList:
  Scope
  ScopeList , Scope

Scope:
  compilation
  reflection
  execution

ServiceName:
  Identifier
  ServiceName . Identifier

ProvidesDirective:
  provides ModuleNameAndVersion ;
  provides service ServiceName with QualifiedIdentifier ;

ExportsDirective:
  exports PackageName ;

PermitsDirective:
  permits ModuleName ;

EntrypointDirective:
  class TypeName ;

ViewDeclaration:
  view ModuleName {
    {ProvidesDirective | ExportsDirective | PermitsDirective | EntrypointDirective}
    }

Chapter 2. ClassFile changes

2.1. Binary form of a module declaration

A compilation unit that contains a module declaration (and potentially additional arbitrary content) is compiled to a ClassFile structure like any other compilation unit.

By convention, the name of a compilation unit that contains a module declaration is module-info.java, echoing the package-info.java convention for a compilation unit that contains solely a package declaration. Consequently, by convention, the name for the compiled form of a module declaration is module-info.class.

A new flag in the ClassFile.access_flags item, ACC_MODULE (0x8000), indicates that the ClassFile represents a module. This flag plays a similar role to ACC_ANNOTATION (0x2000) and ACC_ENUM (0x4000) in flagging this ClassFile as "not a normal class", and does not describe accessibility of a class or interface.

If ACC_MODULE is set in ClassFile.access_flags, then no other flag in ClassFile.access_flags may be set, and the following rules apply to the rest of the ClassFile structure:

  • major_version, minor_version: ≥ 53.0 (i.e. Java SE 9 and above)

  • this_class: [Module's name in internal form (JVMS 4.2.1)]/module-info

    Traditionally, if this_class indicates "P/Q/R", then the ClassFile can be expected to live in a file R.class in a directory P/Q representing a package. This explains why "/module-info" is a suffix in this_class above: if this_class indicates "P/Q/module-info", then the ClassFile can be expected to live in a file module-info.class in a directory P/Q representing a module. The "real name" of the module, shorn of "/module-info", can be obtained from the Module attribute.

  • super_class, interfaces_count, fields_count, methods_count: zero

  • attributes: One Module attribute must be present, to record the name and version of the module. At most one of each of the ModuleRequires, ModuleProvides, and ModuleData attributes may be present. Except for these attributes and Synthetic, SourceFile, SourceDebugExtension, and Deprecated, none of the pre-defined attributes in JVMS 4.7 may appear.

Some notes on compilation:

  • There are no implicit requires dependences at the ClassFile level. That is, if no ModuleRequires.modules table is physically present, then no such table is inferred by the Java virtual machine.

    There will, however, always be a ModuleRequires.modules table in a ClassFile, due to the universal dependence of all modules on java.base. (Compile-time) The ACC_SYNTHESIZED flag is available for a compiler to record that a module declaration in source did not have an explicit requires clause for java.base.

  • There are no implicit re-exports (requires public) at the ClassFile level. That is, the ACC_REEXPORT flag is not set by default in ModuleRequires.modules.

  • There are no implicit scopes for module dependencies at the ClassFile level. That is, a compiler must explicitly set a module dependency's scope in ModuleRequires.modules.module_flags if a target module is required in that scope.

  • There are no implicit exports from views at the ClassFile level. That is, if no ModuleProvides.exports table is physically present, then no such table is inferred by the Java virtual machine.

  • An empty ModuleProvides.permits table means all other modules are permitted.

  • If a module declaration contains a default view, the default view's permits and exports are explicitly copied into the module-info.class file for all non-default views. module-info.class contains explicit permits and exports, with the exception of an empty permits table which implies permits all.

2.2. The Module attribute

Module_attribute {
  u2 attribute_name_index;
  u4 attribute_length;
  u2 module_id_index;
}

The items of the Module_attribute structure are as follows:

attribute_name_index

The value of the attribute_name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing the string "Module".

attribute_length

The value of the attribute_length item must be 2.

module_id_index

The value of the module_id_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_ModuleId_info structure (§2.6) representing the name and version of the module represented by this ClassFile.

The name must be equal to the module name indicated by the ClassFile.this_class item without the "/module-info" suffix.

2.3. The ModuleRequires attribute

ModuleRequires_attribute {
  u2 attribute_name_index;
  u4 attribute_length;
  u2 modules_count;
  { u2 module_index; u4 module_flags; } modules[modules_count];
  u2 services_count;
  { u2 service_index; u4 service_flags; } services[service_count];
}
attribute_name_index

The value of the attribute_name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing the string "ModuleRequires".

attribute_length

The value of the attribute_length item is the length of the attribute excluding the initial six bytes.

modules_count

The value of the modules_count item indicates the number of entries in the modules table.

modules

The value of each module_index entry must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_ModuleQuery_info structure (§2.7) representing a query for a target module on which the module represented by this ClassFile depends. (Compile-time)

A target module name may be referenced by at most one entry in a modules table. (Compile-time)

Unless the ClassFile represents the module java.base, exactly one entry in a modules table must indicate a target module whose name is java.base, and its associated module_flags item must have ACC_COMPILATION_SCOPE and ACC_EXECUTION_SCOPE set and not have ACC_REFLECTION_SCOPE or ACC_SYNTHETIC set. (Compile-time)

The value of the associated module_flags item is as follows:

0x0001 (ACC_COMPILATION_SCOPE)

Indicates that the target module must be present at compile-time. (Compile-time)

0x0002 (ACC_REFLECTION_SCOPE)

Indicates that the target module may be present at run-time. (Compile-time)

0x0004 (ACC_EXECUTION_SCOPE)

Indicates that the target module must be present at run-time. (Compile-time)

0x0010 (ACC_LOCAL)

Indicates that the target module's types must be loaded by the same defining classloader as the types of the module represented by this ClassFile. (Requirement, Compile-time)

0x0020 (ACC_REEXPORT)

Indicates that the module re-exports the visible types which are exported by the target module. (Compile-time)

0x1000 (ACC_SYNTHETIC)

Indicates the dependency is synthetic.

0x10000 (ACC_SYNTHESIZED)

Indicates the dependency is synthesized.

In a module_flags item, at most one of the ACC_REFLECTION_SCOPE and ACC_EXECUTION_SCOPE flags must be set. (Compile-time)

services_count

The value of the services_count item indicates the number of entries in the services table.

services

The value of each services entry must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Class_info structure representing a service (interface or abstract class) on which the module represented by this ClassFile depends. (Requirement)

A service may be referenced by at most one entry in a services table. (Compile-time)

The value of the associated service_flags item is as follows:

0x0001 (ACC_OPTIONAL)

Indicates that this dependency on a service is optional at run-time. (Compile-time)

0x1000 (ACC_SYNTHETIC)

Indicates the dependency is synthetic.

0x10000 (ACC_SYNTHESIZED)

Indicates the dependency is synthesized.

2.4. The ModuleProvides attribute

The range of entities offered by a module to the outside world has grown over time. It started off as aliases (provides) and friends (permits), then added entry points (class) and packages (exports). Recently, services (provides service) were added. Individual attributes for each kind of entity (ModuleProvides, ModulePermits, ModuleEntrypoint, ModuleExports) add little value. The introduction of "views" into the module system - where a view aggregates entities offered by a module, and where a module always has at least one "default" view - suggests a simple ClassFile representation: one attribute defines all views and the entities they offer. This authoritative description of what a module offers is a natural counterpart to the ModuleRequires attribute that describes what a module needs.

ModuleProvides_attribute {
  u2 attribute_name_index;
  u4 attribute_length;
  u2 views_count;
  { u2 view_name_index;
    u2 entrypoint_index;

    u2 aliases_count;
    { u2 alias_index; } aliases[aliases_count];

    u2 services_count;
    { u2 service_index; u2 impl_index; } services[services_count];

    u2 exports_count;
    { u2 export_index; } exports[exports_count];

    u2 permits_count;
    { u2 permit_index; } permits[permit_count];
  } views[views_count];
}
attribute_name_index

The value of the attribute_name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing the string "ModuleProvides".

attribute_length

The value of the attribute_length item is the length of the attribute excluding the initial six bytes.

views_count

The value of the views_count item indicates the number of entries in the views table.

views

Each entry in the views table has the following entries:

view_name_index

The value of the view_name_index item must either be zero (to indicate this is the default view for the module represented by this ClassFile; the view's name is that of the module), or a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing the view's name in internal form (JVMS 4.2.1).

Within the views table, the name of each view (whether a default view or a non-default view) must be unique. (Compile-time)

entrypoint_index

The value of the entrypoint_index item must either be zero (to indicate this view has no entrypoint) or a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Class_info structure representing the name of the class in internal form (JVMS 4.2.1) which is the entrypoint to this view.

aliases_count

The value of the aliases_count item indicates the number of entries in the aliases table.

aliases

The value of each aliases entry must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_ModuleId_info structure (§2.6) representing a module name that is an alias for the module represented by this view. (Compile-time)

Within an entry of the views table, an alias's module name may be referenced by at most one entry in the aliases table. (Compile-time)

services_count

The value of the services_count item indicates the number of entries in the services table.

services

The value of each service_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Class_info structure representing a service (interface or abstract class) provided by this view.

The value of the associated impl_index item in this table must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Class_info structure representing the implementation for the service at service_index.

Within an entry of the views table, at most one entry in the services table may reference the same pair of service_index and impl_index values. (Compile-time)

exports_count

The value of the exports_count item indicates the number of entries in the exports table.

exports

The value of each export_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing the name in internal form (JVMS 4.2.1) of a package to be exported by this view. (Compile-time)

Within an entry of the views table, a package name may be referenced by at most one entry in the exports table. (Compile-time)

permits_count

The value of the permits_count item indicates the number of entries in the permits table.

permits

The value of each permit_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_ModuleId_info structure (§2.6) representing a module which is permitted to have a dependency on the current view. (Compile-time)

It is possible that a module system uses only the name of the permitted module, not its version, in determining visibility.

Within an entry of the views table, a module name may be referenced by at most one entry in the permits table. (Compile-time)

2.5. The ModuleData attribute

ModuleData_attribute {
  u2 attribute_name_index;
  u4 attribute_length;
  u2 data_index;
}
attribute_name_index

The value of the attribute_name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing the string "ModuleData".

attribute_length

The value of the attribute_length item is 2.

data_index

The value of the data_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing the textual content, other than the module declaration, of the compilation unit that declared the module represented by this ClassFile.

2.6. The CONSTANT_ModuleId_info structure

The CONSTANT_ModuleId_info structure in the constant pool is used to represent a pair of a module name and a version.

CONSTANT_ModuleId_info {
  u1 tag;
  u2 name_index;
  u2 version_index;
}
tag

The tag item has the value CONSTANT_ModuleId (19).

name_index

The value of the name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing the module name in internal form (JVMS 4.2.1).

version_index

If the value of the version_index item is not zero, then a version is present. The value must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing a version acceptable to the module system. (Note that there is a standard version format which must be followed or else a ClassFormatError will be thrown. It is simply that the format is not defined by The Java™ Virtual Machine Specification.)

If the value of the version_index item is zero (as opposed to pointing to a CONSTANT_Utf8_info structure which holds the string "0"), then no version is present.

2.7. The CONSTANT_ModuleQuery_info structure

The CONSTANT_ModuleQuery_info structure in the constant pool is used to represent a pair of a module name and a version query.

CONSTANT_ModuleQuery_info {
  u1 tag;
  u2 name_index;
  u2 versionquery_index;
}
tag

The tag item has the value CONSTANT_ModuleQuery (20).

name_index

The value of the name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing the module name in internal form (JVMS 4.2.1).

versionquery_index

If the value of the versionquery_index item is not zero, then a version query is present. The value must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing a version query acceptable to the module system.

If the value of the versionquery_index item is zero (as opposed to pointing to a CONSTANT_Utf8_info structure which holds the string "0"), then no version query is present.