Modules in the Java Language and JVM


Table of Contents

1. Modules in the Java Language
1.1. Module Declarations
1.1.1. Dependences
1.1.2. Exports
1.1.3. Services
2. Modules in the JVM
2.1. Binary form of a module declaration
2.2. The Module attribute
2.3. The ConcealedPackages attribute
2.4. The Version attribute
2.5. The MainClass attribute
2.6. The TargetPlatform attribute

Chapter 1. Modules in the Java Language

1.1. Module Declarations

A compilation unit (JLS 7.3) may contain a module declaration, in which case the filename of the compilation unit is typically module-info.java.


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

ModuleDeclaration:
  module ModuleName { {ModuleStatement} }

ModuleName:
  Identifier
  ModuleName . Identifier

ModuleStatement:
  requires [public] ModuleName ;
  exports PackageName [to ModuleName {, ModuleName}] ;
  uses TypeName ;
  provides TypeName with TypeName ;

Example:

module M.N {
  requires A.B;
  requires public C.D;

  exports P.Q;
  exports R.S to T1.U1, T2.U2;

  uses V.W;
  provides X.Y with Z1.Z2;
  provides X.Y with Z3.Z4;
}

module, requires, exports, to, uses, provides, and with are restricted keywords (i.e. they are keywords solely where they appear as terminals in ModuleDeclaration, and are identifiers everywhere else).

A module declaration introduces a module name that can be used in other module declarations to express relationships between modules. (Requirement) A module name is a qualified identifier, in the spirit of a package name or type name (JLS 6.5). There is no obscuring (JLS 6.4.2) between the name of a module and the name of a variable, type, or package; thus, modules may share names with variables, types, and packages, though it is not necessarily recommended to name a module after a package it contains.

A module declaration may not be annotated.

1.1.1. Dependences

The requires statement takes a qualified identifier indicating the name of a module on which the current module has a dependence. (Requirement)

A requires statement must not appear in the declaration of the java.base module, or a compile-time error occurs, because it is the primordial module and has no dependences. (Compare JLS 8.1.4)

It is a compile-time error if the named module is not observable.

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

It is a compile-time error if the declaration of a module expresses a dependence on itself, either directly or indirectly.

The requires keyword may be followed by the modifier public. This causes any module which depends on the current module to have an implicitly declared dependence on the module specified by the requires public statement.

If the declaration of a module does not express a dependence on the java.base module, and the module is not itself java.base, then the module has an implicitly declared dependence on the java.base module.

1.1.2. Exports

The exports statement takes a qualified identifier indicating the name of a package to be exported from the current module. This makes public types in the package be accessible to code in other modules. (Requirement)

If an exports statement has a to clause, then the package's public types are accessible only to code in the modules specified in the to clause. (Requirement)

It is a compile-time error if the named package is not observable in the current module.

If the named package is observable in the current module, then at least one compilation unit containing a declaration of the package must be observable in the current module, or a compile-time error occurs.

It is a compile-time error if more than one exports statement in a module declaration indicates the same package name.

It is a compile-time error if the to clause of an exports statement indicates a module which is not observable.

It is a compile-time error if the to clause of an exports statement indicates the same module name more than once.

1.1.3. Services

The uses statement takes a qualified identifier indicating the name of a type which is a service interface. (Requirement)

The service interface being used may be declared in the current module or in another module. If the service interface is not declared in the current module, then the service interface must be accessible to the current module, or a compile-time error occurs.

It is a compile-time error if more than one uses statement in a module declaration indicates the same type name.

The provides statement takes a qualified identifier indicating the name of a type which is a service interface, then the with clause indicates the name of a type which is the service implementation. (Requirement)

The service interface being implemented may be declared in the current module or in another module. If the service interface is not declared in the current module, then the service interface must be accessible to the current module, or a compile-time error occurs.

The service implementation must be declared in the current module, or a compile-time error occurs.

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

It is a compile-time error if more than one provides statement in a module declaration indicates the same pair of service interface and service implementation.

Chapter 2. Modules in the JVM

2.1. Binary form of a module declaration

A compilation unit that contains a module declaration is compiled to a ClassFile structure.

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. The ACC_MODULE flag plays a similar role to ACC_ANNOTATION (0x2000) and ACC_ENUM (0x4000) in denoting this ClassFile as "not a normal class". The ACC_MODULE flag 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 occupies a file R.class in a directory representing the package P.Q. Similarly, if this_class indicates P/Q/module-info, then the ClassFile occupies a file module-info.class in a directory representing the module P.Q.

  • super_class, interfaces_count, fields_count, methods_count: zero

  • attributes: One Module attribute must be present. Except for Module, ConcealedPackages, Version, MainClass, TargetPlatform, InnerClasses, Synthetic, SourceFile, SourceDebugExtension, and Deprecated, none of the pre-defined attributes in JVMS 4.7 may appear.

The Module attribute is generally explicit about the module's requirements, permissions, exports, and services:

  • There are no implicit requires statements at the ClassFile level. If the requires_count item is zero, then the Java Virtual Machine does not infer the existence of a requires table nor the existence of any particular entry therein.

    Unless the current module is java.base, the Module attribute will have a requires table of at least length one, because every module (except java.base) depends on java.base. If the source of a module declaration (except java.base) does not state its dependence on java.base explicitly, then a compiler must emit an entry for java.base in the requires table and flag it as ACC_MANDATED to denote that it was implicitly declared. (Compile-time)

  • There are no implicit exports statements at the ClassFile level. If the exports_count item is zero, then the Java Virtual Machine does not infer the existence of an exports table nor the existence of any particular entry therein.

  • Similarly for the uses and provides statements.

There is, however, one place where no information implies something meaningful:

  • In an entry of the exports table, if the exports_to_count item is zero and thus the exports_to_index table is empty, then the Java Virtual Machine allows code in all modules to access the public types of the exported package.

2.2. The Module attribute

The Module attribute is a variable-length attribute in the attributes table of a ClassFile structure. The Module attribute indicates the requirements, permissions, and exported packages of a module, as well as services used by and provided by a module.

There may be at most one Module attribute in the attributes table of a ClassFile structure.

Module_attribute {
    u2 attribute_name_index;
    u4 attribute_length;

    u2 requires_count;
    {   u2 requires_index;
        u2 requires_flags;
    } requires[requires_count];

    u2 exports_count;
    {   u2 exports_index;
        u2 exports_to_count;
        u2 exports_to_index[exports_to_count];
    } exports[exports_count];

    u2 uses_count;
    u2 uses_index[uses_count];

    u2 provides_count;
    {   u2 provides_index; 
        u2 with_index;
    } provides[provides_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 "Module".

attribute_length

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

requires_count

The value of the requires_count item indicates the number of entries in the requires table.

If the current module is java.base, then requires_count must be zero. (Compile-time)

requires[]

Each entry in the requires table represents a dependence of the current module. (Compile-time) The items in each entry are as follows:

requires_index

The value of the requires_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 of a module on which the current module depends.

requires_flags

The value of the requires_flags item is as follows:

0x0020 (ACC_PUBLIC)

Indicates that the current module causes any module which depends on it to implicitly declare a dependence on the module indicated by this entry. (Compile-time)

0x1000 (ACC_SYNTHETIC)

Indicates that the dependence was not explicitly or implicitly declared in the source of the module declaration.

0x8000 (ACC_MANDATED)

Indicates the dependence was implicitly declared in the source of the module declaration.

A module name may be referenced by at most one entry in the requires table. (Compile-time)

Unless the current module is java.base, exactly one entry in the requires table must have a requires_index item indicating java.base and a requires_flags item with the ACC_SYNTHETIC flag not set. (Compile-time)

exports_count

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

exports[]

Each entry in the exports table represents an exported package of the current module. (Compile-time) The items in each entry are as follows:

exports_index

The value of the exports_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 the current module.

A package name may be referenced by at most one entry in the exports table. (Compile-time)

exports_to_count

The value of the exports_to_count indicates the number of entries in the exports_to_index table.

exports_to_index

The value of each exports_to_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 of a module whose code can access the public types in this package. (Compile-time)

A module name may be referenced by at most one entry in the exports_to_index table. (Compile-time)

uses_count

The value of the uses_count item indicates the number of entries in the uses_index table.

uses_index[]

The value of each uses_index 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. (Compile-time)

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

provides_count

The value of the provides_count item indicates the number of entries in the provides table.

provides[]

Each entry in the provides table represents an implementation of a given service. (Compile-time) The items in each entry are as follows:

provides_index

The value of the provides_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 the current module.

with_index

The value of the with_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 the implementation for the service at provides_index.

At most one entry in the provides table may reference the same pair of provides_index and with_index values. (Compile-time)

2.3. The ConcealedPackages attribute

The ConcealedPackages attribute is a variable-length attribute in the attributes table of a ClassFile structure. The ConcealedPackages attribute indicates the non-exported packages of a module.

There may be at most one ConcealedPackages attribute in the attributes table of a ClassFile structure.

ConcealedPackages_attribute {
    u2 attribute_name_index;
    u4 attribute_length;

    u2 packages_count;
    {   u2 package_index;
    } packages[package_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 "ConcealedPackages".

attribute_length

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

packages_count

The value of the packages_count item indicates the number of entries in the packages table.

packages[]

Each entry in the packages table indicates the name of a concealed package. The items in each entry are as follows:

package_index

The value of the package_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 of a package in the current module that is not to be exported.

A package name may be referenced by at most one entry in the packages table.

2.4. The Version attribute

The Version attribute is a fixed-length attribute in the attributes table of a ClassFile structure. The Version attribute indicates the version of a module.

There may be at most one Version attribute in the attributes table of a ClassFile structure.

Version_attribute {
    u2 attribute_name_index;
    u4 attribute_length;

    u2 version_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 "Version".

attribute_length

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

version_index

The value of the version_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 version of the current module.

2.5. The MainClass attribute

The MainClass attribute is a fixed-length attribute in the attributes table of a ClassFile structure. The MainClass attribute indicates the fully qualified name of the main class of a module.

There may be at most one MainClass attribute in the attributes table of a ClassFile structure.

MainClass_attribute {
    u2 attribute_name_index;
    u4 attribute_length;

    u2 main_class_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 "MainClass".

attribute_length

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

main_class_index

The value of the version_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 the main class of the current module.

2.6. The TargetPlatform attribute

The TargetPlatform attribute is a fixed-length attribute in the attributes table of a ClassFile structure. The TargetPlatform attribute indicates the operating system required by a module.

There may be at most one TargetPlatform attribute in the attributes table of a ClassFile structure.

TargetPlatform_attribute {
    u2 attribute_name_index;
    u4 attribute_length;

    u2 os_name_index;
    u2 os_arch_index;
    u2 os_version_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 "TargetPlatform".

attribute_length

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

os_name_index, os_arch_index, os_version_index

The value of each of the os_name_index, os_arch_index, and os_version_index items must be either zero or a valid index into the constant_pool table. If the value of an item is zero, then no information is present for that item. If the value of an item is nonzero, then the constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing the operating system name, architecture, or version (as appropriate for the item) that is required by the current module.