Discussion:
module-info.class spec and attributes
Jonathan Gibbons
2011-06-21 18:47:06 UTC
Permalink
Jigsaw folk,

We have a reasonably up-to-date proposed simple spec for module-info.java
http://openjdk.java.net/projects/jigsaw/doc/topics/grammar.html

But, I don't seem to be able to find a corresponding simple spec for
module-info.class. I've looked on the Jigsaw group web pages and back
(way back) in email. At the time, I believe Alex was giving me marked up
JVMS chapters. The most recent ones I have were from June/July 2009, and
represent a direction we never took -- a single ModuleDirectives
ModuleDirectives_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 directives_length;
{
u2 directive_name_index;
u2 directive_flags;
u4 terms_length;
{ u1 term_type; u2 term_index; } terms_table[term_length];
u2 attributes_count;
attribute_info attributes[attributes_count];
} directives_table[directives_length];
}
So, what is the format we would like to see for module-info.class files?

-- Jon
Alex Buckley
2011-06-25 00:17:20 UTC
Permalink
Post by Jonathan Gibbons
So, what is the format we would like to see for module-info.class files?
Please see attached for a proposal on ClassFile extensions that would
eventually become part of the Java Module System [1].

The proposal refers to the module system requirements document [2] where
necessary.

Alex

[1]http://mail.openjdk.java.net/pipermail/jigsaw-dev/2011-May/001309.html
[2]http://openjdk.java.net/projects/jigsaw/doc/draft-java-module-system-requirements-12
Alex Buckley
2011-06-25 01:01:19 UTC
Permalink
Since attachments seem to be scrubbed, here is the text of the proposal,
obviously without links to the requirements document.


ClassFile changes for Java Modules

Binary form of a module declaration (a.k.a. module-info.class)
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 (0x0800),
indicates that the ClassFile represents a module rather than a class or
interface. Note that this flag plays a similar role to ACC_INTERFACE
(0x0200), 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: >=52.0 (Java SE 8 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: 0
* 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, ModulePermits, ModuleExports,
ModuleClass, 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.

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 module version.

CONSTANT_ModuleId_info {
u1 tag;
// 19
u2 name_index;
// Points to a CONSTANT_Utf8_info representing module name in
internal form (JVMS 4.2.1)
u2 version_index;
// Optionally points to a CONSTANT_Utf8_info representing module
version
}

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

If the version_index item is not 0, then a module version is present.
There is no required structure or semantics for the underlying UTF8
string which represents a module version.

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 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.

The ModuleRequires attribute

ModuleRequires_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 requires_length;
{ u2 requires_index; u1 flags; } requires_table[requires_length];
}

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.
requires_length
The value of the requires_length indicates the number of entries in
the requires_table.
requires_table
Each requires_index must be a valid index into the constant_pool
table. The constant_pool entry at that index must be a
CONSTANT_ModuleId_info structure representing the target module on which
this module depends.
The value of the associated flags item is as follows:

* 0x01 indicates this dependency on the target module is optional.
* 0x02 indictates the target module's types must be loaded by
the same defining classloader as the types of the module represented by
this ClassFile.

A module name may be referenced by at most one entry in a
requires_table.

The ModulePermits attribute

ModulePermits_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 permits_length;
{ u2 permits_index } permits_table[permits_length];
}

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 "ModulePermits".
attribute_length
The value of the attribute_length item is the length of the
attribute excluding the initial six bytes.
permits_length
The value of the permits_length indicates the number of entries in
the permits_table.
permits_table
The value of each permits_index in this 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 representing a module which is
permitted to have a dependency on the module represented by this ClassFile.
(It is possible that a module system uses only the name of the
permitted module, not its version, in determining visibility.)
A module name may be referenced by at most one entry in a
permits_table.

The ModuleProvides attribute

ModuleProvides_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 provides_length;
{ u2 provides_index; } provides_table[provides_length];
}

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.
provides_length
The value of the provides_length indicates the number of entries in
the provides_table.
provides_table
The value of each provides_index in this 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 representing a module that is an
alias for the module represented by this ClassFile.
A module name may be referenced by at most one entry in a
provides_table.

The ModuleExports attribute

ModuleExports_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 exports_length;
{ u2 exports_index; u1 export_kind; u2 source_index; }
exports_table[exports_length];
}

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 "ModuleExports".
attribute_length
The value of the attribute_length item is the length of the
attribute excluding the initial six bytes.
exports_length
The value of the exports_length indicates the number of entries in
the exports_table.
exports_table
The value of each export_index in this 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 an entity to be exported
by the module represented by this ClassFile.
The value of the associated export_kind item indicates the kind of
entity to be exported, as follows:

* 0x01 indicates the entity is a class or interface; it is the
entity to be exported.
* 0x02 indicates the entity is a class or interface; it and its
member types are the entities to be exported.
* 0x04 indicates the entity is a package; the member top-level
classes and interfaces (and their member types) of this package are the
entities to be exported.
* 0x08 indicates the entity is a package; the member top-level
classes and interfaces (and their member types) of this package and all
its subpackages (recursively) are the entities to be exported.

The value of the associated source_index item must be a valid index
into the constant_pool table where the entry is a CONSTANT_ModuleId_info
structure representing the module which declared the exported entity.
(In most cases, where the exported entity is declared in the current
module, source_index will simply point to the same constant pool entry
as the Module attribute. But where the exported entity is re-exported,
source_index may assist resolution and diagnostics.)

The ModuleClass attribute

ModuleClass_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 "ModuleClass".
attribute_length
The value of the attribute_length item is 2.
main_class_index
The value of the main_class_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 name of the class which
is the entrypoint to the module represented by this ClassFile.

The ModuleData attribute

ModuleExtension_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 main_class 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 content, other than the
module declaration, of the compilation unit that declared the module
represented by this ClassFile.
Jonathan Gibbons
2011-06-25 01:22:33 UTC
Permalink
Post by Alex Buckley
The ModuleData attribute
ModuleExtension_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 data_index;
}
-- Jon
Post by Alex Buckley
Since attachments seem to be scrubbed, here is the text of the
proposal, obviously without links to the requirements document.
ClassFile changes for Java Modules
Binary form of a module declaration (a.k.a. module-info.class)
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 (0x0800),
indicates that the ClassFile represents a module rather than a class
or interface. Note that this flag plays a similar role to
ACC_INTERFACE (0x0200), 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
* major_version, minor_version: >=52.0 (Java SE 8 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: 0
* 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, ModulePermits, ModuleExports,
ModuleClass, 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.
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 module version.
CONSTANT_ModuleId_info {
u1 tag;
// 19
u2 name_index;
// Points to a CONSTANT_Utf8_info representing module name in
internal form (JVMS 4.2.1)
u2 version_index;
// Optionally points to a CONSTANT_Utf8_info representing module
version
}
If the version_index item is 0 (as opposed to pointing to a
CONSTANT_Utf8_info structure which holds the string "0"), then no
module version is present.
If the version_index item is not 0, then a module version is present.
There is no required structure or semantics for the underlying UTF8
string which represents a module version.
The Module attribute
Module_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 module_id_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 "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 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.
The ModuleRequires attribute
ModuleRequires_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 requires_length;
{ u2 requires_index; u1 flags; } requires_table[requires_length];
}
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.
requires_length
The value of the requires_length indicates the number of entries
in the requires_table.
requires_table
Each requires_index must be a valid index into the constant_pool
table. The constant_pool entry at that index must be a
CONSTANT_ModuleId_info structure representing the target module on
which this module depends.
* 0x01 indicates this dependency on the target module is optional.
* 0x02 indictates the target module's types must be loaded by
the same defining classloader as the types of the module represented
by this ClassFile.
A module name may be referenced by at most one entry in a
requires_table.
The ModulePermits attribute
ModulePermits_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 permits_length;
{ u2 permits_index } permits_table[permits_length];
}
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
"ModulePermits".
attribute_length
The value of the attribute_length item is the length of the
attribute excluding the initial six bytes.
permits_length
The value of the permits_length indicates the number of entries in
the permits_table.
permits_table
The value of each permits_index in this 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 representing a module which
is permitted to have a dependency on the module represented by this
ClassFile.
(It is possible that a module system uses only the name of the
permitted module, not its version, in determining visibility.)
A module name may be referenced by at most one entry in a
permits_table.
The ModuleProvides attribute
ModuleProvides_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 provides_length;
{ u2 provides_index; } provides_table[provides_length];
}
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.
provides_length
The value of the provides_length indicates the number of entries
in the provides_table.
provides_table
The value of each provides_index in this 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 representing a module
that is an alias for the module represented by this ClassFile.
A module name may be referenced by at most one entry in a
provides_table.
The ModuleExports attribute
ModuleExports_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 exports_length;
{ u2 exports_index; u1 export_kind; u2 source_index; }
exports_table[exports_length];
}
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
"ModuleExports".
attribute_length
The value of the attribute_length item is the length of the
attribute excluding the initial six bytes.
exports_length
The value of the exports_length indicates the number of entries in
the exports_table.
exports_table
The value of each export_index in this 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 an entity to be
exported by the module represented by this ClassFile.
The value of the associated export_kind item indicates the kind of
* 0x01 indicates the entity is a class or interface; it is the
entity to be exported.
* 0x02 indicates the entity is a class or interface; it and
its member types are the entities to be exported.
* 0x04 indicates the entity is a package; the member top-level
classes and interfaces (and their member types) of this package are
the entities to be exported.
* 0x08 indicates the entity is a package; the member top-level
classes and interfaces (and their member types) of this package and
all its subpackages (recursively) are the entities to be exported.
The value of the associated source_index item must be a valid
index into the constant_pool table where the entry is a
CONSTANT_ModuleId_info structure representing the module which
declared the exported entity. (In most cases, where the exported
entity is declared in the current module, source_index will simply
point to the same constant pool entry as the Module attribute. But
where the exported entity is re-exported, source_index may assist
resolution and diagnostics.)
The ModuleClass attribute
ModuleClass_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
"ModuleClass".
attribute_length
The value of the attribute_length item is 2.
main_class_index
The value of the main_class_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 name of the class
which is the entrypoint to the module represented by this ClassFile.
The ModuleData attribute
ModuleExtension_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 main_class 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 content, other than the
module declaration, of the compilation unit that declared the module
represented by this ClassFile.
David Bosschaert
2011-06-28 21:24:19 UTC
Permalink
I wonder why such a binary .class file for module declarations is
really needed. Why not go for a textual file, for instance
META-INF/module-info.jmod (or something like that) and declare the
module declarations in there using a textual format of some sort?

Like the other files in META-INF, it will become part of the ultimate
jar as-is so compilation into a .class file is not needed nor are
extensions to the .class file specification.

IMO there are multiple benefits associated keeping the textual format.
People using the jar can use a simple zip tool to look inside the jar
to see what its dependencies are. Additionally tools can easily be
written to read the module-info.jmod file without needing to resort to
classfile parsing libraries. The module information can be of use to
both developer as well as deployer tools.

Finally it's probably easier to make the textual file extensible, as
required by [1], without resorting to inefficient reflection-style
operations.

Best regards,

David

[1] http://openjdk.java.net/projects/jigsaw/doc/draft-java-module-system-requirements-12#extensible-module-declarations
Post by Jonathan Gibbons
Post by Alex Buckley
The ModuleData attribute
ModuleExtension_attribute {
?u2 attribute_name_index;
?u4 attribute_length;
?u2 data_index;
}
-- Jon
Post by Alex Buckley
Since attachments seem to be scrubbed, here is the text of the proposal,
obviously without links to the requirements document.
ClassFile changes for Java Modules
Binary form of a module declaration (a.k.a. module-info.class)
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 (0x0800),
indicates that the ClassFile represents a module rather than a class or
interface. Note that this flag plays a similar role to ACC_INTERFACE
(0x0200), 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
? ?* major_version, minor_version: >=52.0 (Java SE 8 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
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: 0
? ?* 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, ModulePermits, ModuleExports, ModuleClass, 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.
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 module version.
CONSTANT_ModuleId_info {
?u1 tag;
? ?// 19
?u2 name_index;
? ?// Points to a CONSTANT_Utf8_info representing module name in internal
form (JVMS 4.2.1)
?u2 version_index;
? ?// Optionally points to a CONSTANT_Utf8_info representing module
version
}
If the version_index item is 0 (as opposed to pointing to a
CONSTANT_Utf8_info structure which holds the string "0"), then no module
version is present.
If the version_index item is not 0, then a module version is present.
There is no required structure or semantics for the underlying UTF8 string
which represents a module version.
The Module attribute
Module_attribute {
?u2 attribute_name_index;
?u4 attribute_length;
?u2 module_id_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 "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 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.
The ModuleRequires attribute
ModuleRequires_attribute {
?u2 attribute_name_index;
?u4 attribute_length;
?u2 requires_length;
?{ u2 requires_index; u1 flags; } requires_table[requires_length];
}
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.
requires_length
? ?The value of the requires_length indicates the number of entries in the
requires_table.
requires_table
? ?Each requires_index must be a valid index into the constant_pool table.
The constant_pool entry at that index must be a CONSTANT_ModuleId_info
structure representing the target module on which this module depends.
? ? ? ?* 0x01 indicates this dependency on the target module is optional.
? ? ? ?* 0x02 indictates the target module's types must be loaded by the
same defining classloader as the types of the module represented by this
ClassFile.
? ?A module name may be referenced by at most one entry in a
requires_table.
The ModulePermits attribute
ModulePermits_attribute {
?u2 attribute_name_index;
?u4 attribute_length;
?u2 permits_length;
?{ u2 permits_index } permits_table[permits_length];
}
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 "ModulePermits".
attribute_length
? ?The value of the attribute_length item is the length of the attribute
excluding the initial six bytes.
permits_length
? ?The value of the permits_length indicates the number of entries in the
permits_table.
permits_table
? ?The value of each permits_index in this 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 representing a module which is permitted to
have a dependency on the module represented by this ClassFile.
? ?(It is possible that a module system uses only the name of the
permitted module, not its version, in determining visibility.)
? ?A module name may be referenced by at most one entry in a
permits_table.
The ModuleProvides attribute
ModuleProvides_attribute {
?u2 attribute_name_index;
?u4 attribute_length;
?u2 provides_length;
?{ u2 provides_index; } provides_table[provides_length];
}
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.
provides_length
? ?The value of the provides_length indicates the number of entries in the
provides_table.
provides_table
? ?The value of each provides_index in this 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 representing a module that is an alias
for the module represented by this ClassFile.
? ?A module name may be referenced by at most one entry in a
provides_table.
The ModuleExports attribute
ModuleExports_attribute {
?u2 attribute_name_index;
?u4 attribute_length;
?u2 exports_length;
?{ u2 exports_index; u1 export_kind; u2 source_index; }
exports_table[exports_length];
}
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 "ModuleExports".
attribute_length
? ?The value of the attribute_length item is the length of the attribute
excluding the initial six bytes.
exports_length
? ?The value of the exports_length indicates the number of entries in the
exports_table.
exports_table
? ?The value of each export_index in this 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 an entity to be exported by the
module represented by this ClassFile.
? ?The value of the associated export_kind item indicates the kind of
? ? ? ?* 0x01 indicates the entity is a class or interface; it is the
entity to be exported.
? ? ? ?* 0x02 indicates the entity is a class or interface; it and its
member types are the entities to be exported.
? ? ? ?* 0x04 indicates the entity is a package; the member top-level
classes and interfaces (and their member types) of this package are the
entities to be exported.
? ? ? ?* 0x08 indicates the entity is a package; the member top-level
classes and interfaces (and their member types) of this package and all its
subpackages (recursively) are the entities to be exported.
? ?The value of the associated source_index item must be a valid index
into the constant_pool table where the entry is a CONSTANT_ModuleId_info
structure representing the module which declared the exported entity. (In
most cases, where the exported entity is declared in the current module,
source_index will simply point to the same constant pool entry as the Module
attribute. But where the exported entity is re-exported, source_index may
assist resolution and diagnostics.)
The ModuleClass attribute
ModuleClass_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 "ModuleClass".
attribute_length
? ?The value of the attribute_length item is 2.
main_class_index
? ?The value of the main_class_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 name of the class which is
the entrypoint to the module represented by this ClassFile.
The ModuleData attribute
ModuleExtension_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 main_class 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 content, other than the module
declaration, of the compilation unit that declared the module represented by
this ClassFile.
David M. Lloyd
2011-06-29 03:43:15 UTC
Permalink
Yeah I agree, following the mold of classes and package-info is a big
mistake here. Not sure if it's simple cargo-cultism or what.

In JBoss Modules we actually use XML, and performance is very good. If
you used a dedicated text format I'm sure that performance would be
quite good enough at runtime.
Post by David Bosschaert
I wonder why such a binary .class file for module declarations is
really needed. Why not go for a textual file, for instance
META-INF/module-info.jmod (or something like that) and declare the
module declarations in there using a textual format of some sort?
Like the other files in META-INF, it will become part of the ultimate
jar as-is so compilation into a .class file is not needed nor are
extensions to the .class file specification.
IMO there are multiple benefits associated keeping the textual format.
People using the jar can use a simple zip tool to look inside the jar
to see what its dependencies are. Additionally tools can easily be
written to read the module-info.jmod file without needing to resort to
classfile parsing libraries. The module information can be of use to
both developer as well as deployer tools.
Finally it's probably easier to make the textual file extensible, as
required by [1], without resorting to inefficient reflection-style
operations.
Best regards,
David
[1] http://openjdk.java.net/projects/jigsaw/doc/draft-java-module-system-requirements-12#extensible-module-declarations
Post by Jonathan Gibbons
Post by Alex Buckley
The ModuleData attribute
ModuleExtension_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 data_index;
}
-- Jon
Post by Alex Buckley
Since attachments seem to be scrubbed, here is the text of the proposal,
obviously without links to the requirements document.
ClassFile changes for Java Modules
Binary form of a module declaration (a.k.a. module-info.class)
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 (0x0800),
indicates that the ClassFile represents a module rather than a class or
interface. Note that this flag plays a similar role to ACC_INTERFACE
(0x0200), 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
* major_version, minor_version:>=52.0 (Java SE 8 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
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: 0
* 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, ModulePermits, ModuleExports, ModuleClass, 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.
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 module version.
CONSTANT_ModuleId_info {
u1 tag;
// 19
u2 name_index;
// Points to a CONSTANT_Utf8_info representing module name in internal
form (JVMS 4.2.1)
u2 version_index;
// Optionally points to a CONSTANT_Utf8_info representing module
version
}
If the version_index item is 0 (as opposed to pointing to a
CONSTANT_Utf8_info structure which holds the string "0"), then no module
version is present.
If the version_index item is not 0, then a module version is present.
There is no required structure or semantics for the underlying UTF8 string
which represents a module version.
The Module attribute
Module_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 module_id_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 "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 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.
The ModuleRequires attribute
ModuleRequires_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 requires_length;
{ u2 requires_index; u1 flags; } requires_table[requires_length];
}
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.
requires_length
The value of the requires_length indicates the number of entries in the
requires_table.
requires_table
Each requires_index must be a valid index into the constant_pool table.
The constant_pool entry at that index must be a CONSTANT_ModuleId_info
structure representing the target module on which this module depends.
* 0x01 indicates this dependency on the target module is optional.
* 0x02 indictates the target module's types must be loaded by the
same defining classloader as the types of the module represented by this
ClassFile.
A module name may be referenced by at most one entry in a
requires_table.
The ModulePermits attribute
ModulePermits_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 permits_length;
{ u2 permits_index } permits_table[permits_length];
}
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 "ModulePermits".
attribute_length
The value of the attribute_length item is the length of the attribute
excluding the initial six bytes.
permits_length
The value of the permits_length indicates the number of entries in the
permits_table.
permits_table
The value of each permits_index in this 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 representing a module which is permitted to
have a dependency on the module represented by this ClassFile.
(It is possible that a module system uses only the name of the
permitted module, not its version, in determining visibility.)
A module name may be referenced by at most one entry in a
permits_table.
The ModuleProvides attribute
ModuleProvides_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 provides_length;
{ u2 provides_index; } provides_table[provides_length];
}
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.
provides_length
The value of the provides_length indicates the number of entries in the
provides_table.
provides_table
The value of each provides_index in this 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 representing a module that is an alias
for the module represented by this ClassFile.
A module name may be referenced by at most one entry in a
provides_table.
The ModuleExports attribute
ModuleExports_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 exports_length;
{ u2 exports_index; u1 export_kind; u2 source_index; }
exports_table[exports_length];
}
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 "ModuleExports".
attribute_length
The value of the attribute_length item is the length of the attribute
excluding the initial six bytes.
exports_length
The value of the exports_length indicates the number of entries in the
exports_table.
exports_table
The value of each export_index in this 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 an entity to be exported by the
module represented by this ClassFile.
The value of the associated export_kind item indicates the kind of
* 0x01 indicates the entity is a class or interface; it is the
entity to be exported.
* 0x02 indicates the entity is a class or interface; it and its
member types are the entities to be exported.
* 0x04 indicates the entity is a package; the member top-level
classes and interfaces (and their member types) of this package are the
entities to be exported.
* 0x08 indicates the entity is a package; the member top-level
classes and interfaces (and their member types) of this package and all its
subpackages (recursively) are the entities to be exported.
The value of the associated source_index item must be a valid index
into the constant_pool table where the entry is a CONSTANT_ModuleId_info
structure representing the module which declared the exported entity. (In
most cases, where the exported entity is declared in the current module,
source_index will simply point to the same constant pool entry as the Module
attribute. But where the exported entity is re-exported, source_index may
assist resolution and diagnostics.)
The ModuleClass attribute
ModuleClass_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 "ModuleClass".
attribute_length
The value of the attribute_length item is 2.
main_class_index
The value of the main_class_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 name of the class which is
the entrypoint to the module represented by this ClassFile.
The ModuleData attribute
ModuleExtension_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 main_class 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 content, other than the module
declaration, of the compilation unit that declared the module represented by
this ClassFile.
--
- DML
Alex Buckley
2011-06-30 00:07:07 UTC
Permalink
(Sent this mail yesterday but I think it got lost.)
Post by David Bosschaert
I wonder why such a binary .class file for module declarations is
really needed. Why not go for a textual file, for instance
META-INF/module-info.jmod (or something like that) and declare the
module declarations in there using a textual format of some sort?
The arguments for a binary compiled form are given at:

http://openjdk.java.net/projects/jigsaw/doc/draft-java-module-system-requirements-12#_C
Post by David Bosschaert
IMO there are multiple benefits associated keeping the textual format.
People using the jar can use a simple zip tool to look inside the jar
to see what its dependencies are. Additionally tools can easily be
written to read the module-info.jmod file without needing to resort to
classfile parsing libraries. The module information can be of use to
both developer as well as deployer tools.
Finally it's probably easier to make the textual file extensible, as
required by [1], without resorting to inefficient reflection-style
operations.
I think these points are also captured in Appendix C. Could not the same
points have been made in favor of a textual format for class and
interface declarations?

Alex
David M. Lloyd
2011-06-30 00:24:17 UTC
Permalink
Post by Alex Buckley
(Sent this mail yesterday but I think it got lost.)
Post by David Bosschaert
I wonder why such a binary .class file for module declarations is
really needed. Why not go for a textual file, for instance
META-INF/module-info.jmod (or something like that) and declare the
module declarations in there using a textual format of some sort?
http://openjdk.java.net/projects/jigsaw/doc/draft-java-module-system-requirements-12#_C
All of which are trivially debunkable. Yes, it is *slightly* more
efficient to read structured binary than a text format. It is an
insignificant difference though. We actually parse ours as XML using
StAX, which should be somewhat more expensive than a dedicated text
parser, and it's so fast that I'm not even able to get a significant
measurement of the time when booting up a 100+ module project. The
performance argument is invalid.

And constraining the module metadata to a Java-like syntax with a
Java-like file name is just a dumb idea. There's no reason for it.

Saying that requiring a tool to modify the metadata for a module is
somehow a good thing is pretty off the wall too. I mean just crazy.

Come down to Earth guys.
Post by Alex Buckley
Post by David Bosschaert
IMO there are multiple benefits associated keeping the textual format.
People using the jar can use a simple zip tool to look inside the jar
to see what its dependencies are. Additionally tools can easily be
written to read the module-info.jmod file without needing to resort to
classfile parsing libraries. The module information can be of use to
both developer as well as deployer tools.
Finally it's probably easier to make the textual file extensible, as
required by [1], without resorting to inefficient reflection-style
operations.
I think these points are also captured in Appendix C. Could not the same
points have been made in favor of a textual format for class and
interface declarations?
Yup. But that ship has sailed. A binary format for module
meta-information is going to be yet another annoying disaster.
--
- DML
Alex Buckley
2011-06-30 00:46:28 UTC
Permalink
In the context of Project Jigsaw, javac parses module declarations every
time a source file in a modular directory structure is compiled. That's
a powerful driver for Java-like source syntax and a class file form.

Projects which don't put module information so close to the compiler may
well choose other forms.

Alex
Post by David M. Lloyd
Post by Alex Buckley
(Sent this mail yesterday but I think it got lost.)
Post by David Bosschaert
I wonder why such a binary .class file for module declarations is
really needed. Why not go for a textual file, for instance
META-INF/module-info.jmod (or something like that) and declare the
module declarations in there using a textual format of some sort?
http://openjdk.java.net/projects/jigsaw/doc/draft-java-module-system-requirements-12#_C
All of which are trivially debunkable. Yes, it is *slightly* more
efficient to read structured binary than a text format. It is an
insignificant difference though. We actually parse ours as XML using
StAX, which should be somewhat more expensive than a dedicated text
parser, and it's so fast that I'm not even able to get a significant
measurement of the time when booting up a 100+ module project. The
performance argument is invalid.
And constraining the module metadata to a Java-like syntax with a
Java-like file name is just a dumb idea. There's no reason for it.
Saying that requiring a tool to modify the metadata for a module is
somehow a good thing is pretty off the wall too. I mean just crazy.
Come down to Earth guys.
Post by Alex Buckley
Post by David Bosschaert
IMO there are multiple benefits associated keeping the textual format.
People using the jar can use a simple zip tool to look inside the jar
to see what its dependencies are. Additionally tools can easily be
written to read the module-info.jmod file without needing to resort to
classfile parsing libraries. The module information can be of use to
both developer as well as deployer tools.
Finally it's probably easier to make the textual file extensible, as
required by [1], without resorting to inefficient reflection-style
operations.
I think these points are also captured in Appendix C. Could not the same
points have been made in favor of a textual format for class and
interface declarations?
Yup. But that ship has sailed. A binary format for module
meta-information is going to be yet another annoying disaster.
David M. Lloyd
2011-06-30 01:00:14 UTC
Permalink
Not really. In fact that's basically using the (apparently poor) design
choices of the compiler to justify this, which I find to be exceedingly
weak.

The compiler should never need to parse module information more than
once per compilation, regardless of how many source files are compiled.
If it's requiring that, fix the real problem, rather than using it as
justification for crap decisions elsewhere.
Post by Alex Buckley
In the context of Project Jigsaw, javac parses module declarations every
time a source file in a modular directory structure is compiled. That's
a powerful driver for Java-like source syntax and a class file form.
Projects which don't put module information so close to the compiler may
well choose other forms.
Alex
Post by Alex Buckley
(Sent this mail yesterday but I think it got lost.)
Post by David Bosschaert
I wonder why such a binary .class file for module declarations is
really needed. Why not go for a textual file, for instance
META-INF/module-info.jmod (or something like that) and declare the
module declarations in there using a textual format of some sort?
http://openjdk.java.net/projects/jigsaw/doc/draft-java-module-system-requirements-12#_C
All of which are trivially debunkable. Yes, it is *slightly* more
efficient to read structured binary than a text format. It is an
insignificant difference though. We actually parse ours as XML using
StAX, which should be somewhat more expensive than a dedicated text
parser, and it's so fast that I'm not even able to get a significant
measurement of the time when booting up a 100+ module project. The
performance argument is invalid.
And constraining the module metadata to a Java-like syntax with a
Java-like file name is just a dumb idea. There's no reason for it.
Saying that requiring a tool to modify the metadata for a module is
somehow a good thing is pretty off the wall too. I mean just crazy.
Come down to Earth guys.
Post by Alex Buckley
Post by David Bosschaert
IMO there are multiple benefits associated keeping the textual format.
People using the jar can use a simple zip tool to look inside the jar
to see what its dependencies are. Additionally tools can easily be
written to read the module-info.jmod file without needing to resort to
classfile parsing libraries. The module information can be of use to
both developer as well as deployer tools.
Finally it's probably easier to make the textual file extensible, as
required by [1], without resorting to inefficient reflection-style
operations.
I think these points are also captured in Appendix C. Could not the same
points have been made in favor of a textual format for class and
interface declarations?
Yup. But that ship has sailed. A binary format for module
meta-information is going to be yet another annoying disaster.
--
- DML
Alex Buckley
2011-06-30 02:51:59 UTC
Permalink
I think we're slightly missing each other here. I wasn't implying javac
is unable to cache module declarations; rather that module declarations
are now woven deeply into compilation because determining the visibility
of _any_ type (whether available in source or class file form) is
dependent on a graph of module declarations (possibly cached by the
module system, but not when the world is being built from source).
Jigsaw is just keeping the structure of those module declarations in
source/binary forms that compilers are familiar with.

Alex
Post by David M. Lloyd
Not really. In fact that's basically using the (apparently poor) design
choices of the compiler to justify this, which I find to be exceedingly
weak.
The compiler should never need to parse module information more than
once per compilation, regardless of how many source files are compiled.
If it's requiring that, fix the real problem, rather than using it as
justification for crap decisions elsewhere.
Post by Alex Buckley
In the context of Project Jigsaw, javac parses module declarations every
time a source file in a modular directory structure is compiled. That's
a powerful driver for Java-like source syntax and a class file form.
Projects which don't put module information so close to the compiler may
well choose other forms.
Alex
Post by Alex Buckley
(Sent this mail yesterday but I think it got lost.)
Post by David Bosschaert
I wonder why such a binary .class file for module declarations is
really needed. Why not go for a textual file, for instance
META-INF/module-info.jmod (or something like that) and declare the
module declarations in there using a textual format of some sort?
http://openjdk.java.net/projects/jigsaw/doc/draft-java-module-system-requirements-12#_C
All of which are trivially debunkable. Yes, it is *slightly* more
efficient to read structured binary than a text format. It is an
insignificant difference though. We actually parse ours as XML using
StAX, which should be somewhat more expensive than a dedicated text
parser, and it's so fast that I'm not even able to get a significant
measurement of the time when booting up a 100+ module project. The
performance argument is invalid.
And constraining the module metadata to a Java-like syntax with a
Java-like file name is just a dumb idea. There's no reason for it.
Saying that requiring a tool to modify the metadata for a module is
somehow a good thing is pretty off the wall too. I mean just crazy.
Come down to Earth guys.
Post by Alex Buckley
Post by David Bosschaert
IMO there are multiple benefits associated keeping the textual format.
People using the jar can use a simple zip tool to look inside the jar
to see what its dependencies are. Additionally tools can easily be
written to read the module-info.jmod file without needing to resort to
classfile parsing libraries. The module information can be of use to
both developer as well as deployer tools.
Finally it's probably easier to make the textual file extensible, as
required by [1], without resorting to inefficient reflection-style
operations.
I think these points are also captured in Appendix C. Could not the same
points have been made in favor of a textual format for class and
interface declarations?
Yup. But that ship has sailed. A binary format for module
meta-information is going to be yet another annoying disaster.
Rémi Forax
2011-06-30 07:09:57 UTC
Permalink
David,
I think storing the module metadata as a class file is a brilliant idea.

First you have to think that what we want is not one text file but two.
Some module metadata are generated (the one marked synthetic in the
current format)
by the compiler and as a user I don't want to see them, edit them, etc.

Eclipse plugins use the approach of having one file for the two
purposes, be a module
descriptor editable by a human and be a module deployment descriptor
readable
by the module runtime.
As a user, the experience is painful, the file is big and a big part of
the data are useless
and sometimes you have to reconcile the state of the source and the
plugin descriptor
by hand.

To summarize, we need a file which is readable/writable by a human,
readable by the compiler
and the compiler need to generate a module deployment from it that need
to be readable
by the module runtime system.
Hence, it's logical to have a Java file and a class file.

Also a classfile is versioned, compact, has no character encoding problem,
is well integrated with the other files and as Alex said is more
efficient than an XML file.

Another cool point is that because the module descriptor is a Java file
you know
where to put the module doc :)

R?mi
Post by Alex Buckley
I think we're slightly missing each other here. I wasn't implying
javac is unable to cache module declarations; rather that module
declarations are now woven deeply into compilation because determining
the visibility of _any_ type (whether available in source or class
file form) is dependent on a graph of module declarations (possibly
cached by the module system, but not when the world is being built
from source). Jigsaw is just keeping the structure of those module
declarations in source/binary forms that compilers are familiar with.
Alex
Post by David M. Lloyd
Not really. In fact that's basically using the (apparently poor)
design choices of the compiler to justify this, which I find to be
exceedingly weak.
The compiler should never need to parse module information more than
once per compilation, regardless of how many source files are
compiled. If it's requiring that, fix the real problem, rather than
using it as justification for crap decisions elsewhere.
Post by Alex Buckley
In the context of Project Jigsaw, javac parses module declarations every
time a source file in a modular directory structure is compiled. That's
a powerful driver for Java-like source syntax and a class file form.
Projects which don't put module information so close to the compiler may
well choose other forms.
Alex
Post by Alex Buckley
(Sent this mail yesterday but I think it got lost.)
Post by David Bosschaert
I wonder why such a binary .class file for module declarations is
really needed. Why not go for a textual file, for instance
META-INF/module-info.jmod (or something like that) and declare the
module declarations in there using a textual format of some sort?
http://openjdk.java.net/projects/jigsaw/doc/draft-java-module-system-requirements-12#_C
All of which are trivially debunkable. Yes, it is *slightly* more
efficient to read structured binary than a text format. It is an
insignificant difference though. We actually parse ours as XML using
StAX, which should be somewhat more expensive than a dedicated text
parser, and it's so fast that I'm not even able to get a significant
measurement of the time when booting up a 100+ module project. The
performance argument is invalid.
And constraining the module metadata to a Java-like syntax with a
Java-like file name is just a dumb idea. There's no reason for it.
Saying that requiring a tool to modify the metadata for a module is
somehow a good thing is pretty off the wall too. I mean just crazy.
Come down to Earth guys.
Post by Alex Buckley
Post by David Bosschaert
IMO there are multiple benefits associated keeping the textual format.
People using the jar can use a simple zip tool to look inside the jar
to see what its dependencies are. Additionally tools can easily be
written to read the module-info.jmod file without needing to resort to
classfile parsing libraries. The module information can be of use to
both developer as well as deployer tools.
Finally it's probably easier to make the textual file extensible, as
required by [1], without resorting to inefficient reflection-style
operations.
I think these points are also captured in Appendix C. Could not the same
points have been made in favor of a textual format for class and
interface declarations?
Yup. But that ship has sailed. A binary format for module
meta-information is going to be yet another annoying disaster.
Peter Kriens
2011-07-04 08:50:29 UTC
Permalink
This post might be inappropriate. Click to display it.
David Bosschaert
2011-08-25 13:00:57 UTC
Permalink
Reviving an old thread... it seems like this discussion is left
without coming to an agreed conclusion.

On the one hand we have Alex and Remi arguing for a binary runtime
format for the module-metadata.
On the other we have a number of people (Peter, David L and me)
arguing for a textual format for the module metadata.

Let me try to summarize the points made so far.

Points in favour of a binary, compiled format:
* More efficient to read at runtime (have we got numbers to prove this?)
* Because the source is in a .java file the runtime must be in a .class file
* Helps to ensure validity
* Can more easily be handled by javac

Not compiled (e.g. a DSL, XML or a text file similar to that)
* Can easily be processed by external tools
* Can easily be read and understood by humans
* Can easily be processed by other module systems (e.g. OSGi, JBoss Modules)
* The .class file structure is not the best format for storing module metadata

I hope I captured both sides accurately - please chime in if I didn't :)

It would be great if we could come to some common agreement here...
Anyone else any thoughts?

Best regards,

David
Post by Peter Kriens
I think you conflate the fact that a file is based on a textual format with the fact that it is edited. Files like the manifest and XML files are not human editable although many developers are too lazy to provide a proper front end and offer those files as human editable. They are intended for machine-machine communication with the added benefit that they are easy to verify when things go awry. Our industry learned that lesson the hard way over the past few decades.
? ? ? ?import package com.acme.foo.*;
? ? ? ?module BAR implements JDK17 {
? ? ? ? ? ? ? ?package com.sun.misc;
? ? ? ? ? ? ? ?package com.sun.impl.java.lang;
? ? ? ? ? ? ? ?void main(String args[] ) {
? ? ? ? ? ? ? ? ? ? ? ?...
? ? ? ? ? ? ? ?}
? ? ? ?}
As it is now, the class file is just a set of attributes. XML was invented for exactly this purpose, not as a human editable file, but as a file that allows different parties to integrate their information in a single file without having to worry about character sets and collisions. If Jigsaw defines a proper schema, the OSGi and others can add a namespace on each element to carry their metadata.
Post by RĂƒÂ©mi Forax
David,
I think storing the module metadata as a class file is a brilliant idea.
:-)
Post by RĂƒÂ©mi Forax
First you have to think that what we want is not one text file but two.
Some module metadata are generated (the one marked synthetic in the current format)
by the compiler and as a user I don't want to see them, edit them, etc.
Fully agree, the "binary" version is like the manifest in OSGi, not intended for human consumption with its limited line length. However, when things go awry it is very nice to be able to see them without requiring specialized tools.
Post by RĂƒÂ©mi Forax
Eclipse plugins use the approach of having one file for the two purposes, be a module
descriptor editable by a human and be a module deployment descriptor readable
by the module runtime. As a user, the experience is painful, the file is big and a big part of the data are useless
and sometimes you have to reconcile the state of the source and the plugin descriptor
by hand.
That is why this method is disputed. Manifest is a binary format and you should not be edited by hand. That is why for example bndtools and maven generate the manifest.
Post by RĂƒÂ©mi Forax
To summarize, we need a file which is readable/writable by a human, readable by the compiler
and the compiler need to generate a module deployment from it that need to be readable
by the module runtime system. Hence, it's logical to have a Java file and a class file.
Though I agree with the Java source file I fail to see why the output needs to be a Java class file as the module as currently designed does not even remotely look like a class. If it did, (a Module also has members) the story would be different.
Post by RĂƒÂ©mi Forax
Also a classfile is versioned, compact, has no character encoding problem,
is well integrated with the other files and as Alex said is more efficient than an XML file.
As the manifest will be compressed by the JAR file the efficiency gain is minimal as the binary class file compresses worse, if relevant at the first place. And if this is an issue, there are even better formats.
Post by RĂƒÂ©mi Forax
Another cool point is that because the module descriptor is a Java file you know
where to put the module doc :)
Which makes the module namespace overlap with the package namespace ... which I think will cause some nasty unnecessary constraints as a modules should encapsulate a package namespace and not be part of it.
Kind regards,
? ? ? ?Peter Kriens
Post by RĂƒÂ©mi Forax
R?mi
I think we're slightly missing each other here. I wasn't implying javac is unable to cache module declarations; rather that module declarations are now woven deeply into compilation because determining the visibility of _any_ type (whether available in source or class file form) is dependent on a graph of module declarations (possibly cached by the module system, but not when the world is being built from source). Jigsaw is just keeping the structure of those module declarations in source/binary forms that compilers are familiar with.
Alex
Not really. ?In fact that's basically using the (apparently poor) design choices of the compiler to justify this, which I find to be exceedingly weak.
The compiler should never need to parse module information more than once per compilation, regardless of how many source files are compiled. ?If it's requiring that, fix the real problem, rather than using it as justification for crap decisions elsewhere.
Post by Alex Buckley
In the context of Project Jigsaw, javac parses module declarations every
time a source file in a modular directory structure is compiled. That's
a powerful driver for Java-like source syntax and a class file form.
Projects which don't put module information so close to the compiler may
well choose other forms.
Alex
Post by Alex Buckley
(Sent this mail yesterday but I think it got lost.)
Post by David Bosschaert
I wonder why such a binary .class file for module declarations is
really needed. Why not go for a textual file, for instance
META-INF/module-info.jmod (or something like that) and declare the
module declarations in there using a textual format of some sort?
http://openjdk.java.net/projects/jigsaw/doc/draft-java-module-system-requirements-12#_C
All of which are trivially debunkable. Yes, it is *slightly* more
efficient to read structured binary than a text format. It is an
insignificant difference though. We actually parse ours as XML using
StAX, which should be somewhat more expensive than a dedicated text
parser, and it's so fast that I'm not even able to get a significant
measurement of the time when booting up a 100+ module project. The
performance argument is invalid.
And constraining the module metadata to a Java-like syntax with a
Java-like file name is just a dumb idea. There's no reason for it.
Saying that requiring a tool to modify the metadata for a module is
somehow a good thing is pretty off the wall too. I mean just crazy.
Come down to Earth guys.
Post by Alex Buckley
Post by David Bosschaert
IMO there are multiple benefits associated keeping the textual format.
People using the jar can use a simple zip tool to look inside the jar
to see what its dependencies are. Additionally tools can easily be
written to read the module-info.jmod file without needing to resort to
classfile parsing libraries. The module information can be of use to
both developer as well as deployer tools.
Finally it's probably easier to make the textual file extensible, as
required by [1], without resorting to inefficient reflection-style
operations.
I think these points are also captured in Appendix C. Could not the same
points have been made in favor of a textual format for class and
interface declarations?
Yup. But that ship has sailed. A binary format for module
meta-information is going to be yet another annoying disaster.
Alan Bateman
2011-08-25 13:22:13 UTC
Permalink
Post by David Bosschaert
Reviving an old thread... it seems like this discussion is left
without coming to an agreed conclusion.
It's an issue where there are divergent views so I don't think you'll
see agreement here. For now, capturing the arguments in the requirements
document seems the right approach.

-Alan.
Alex Buckley
2011-08-25 23:54:28 UTC
Permalink
Post by Alan Bateman
Post by David Bosschaert
Reviving an old thread... it seems like this discussion is left
without coming to an agreed conclusion.
It's an issue where there are divergent views so I don't think you'll
see agreement here. For now, capturing the arguments in the requirements
document seems the right approach.
Right. As David says, the arguments for and against various schemes are
very well understood. OpenJDK Project Jigsaw is prototyping one scheme,
but the final choice of scheme is not up to the Project, it's up to the
Expert Group of the Java SE Module System JSR.

Alex
David Bosschaert
2011-08-26 07:48:08 UTC
Permalink
Post by David Bosschaert
Reviving an old thread... it seems like this discussion is left
without coming to an agreed conclusion.
It's an issue where there are divergent views so I don't think you'll see
agreement here. For now, capturing the arguments in the requirements
document seems the right approach.
Right. As David says, the arguments for and against various schemes are very
well understood. OpenJDK Project Jigsaw is prototyping one scheme, but the
final choice of scheme is not up to the Project, it's up to the Expert Group
of the Java SE Module System JSR.
Alex
Hi Alex,

When can we expect that JSR being formed? It's currently listed on
http://jcp.org/en/jsr/detail?id=337 as 'JSR TBD: Java Platform Module
System'.

Thanks,

David
Alex Buckley
2011-08-26 18:02:26 UTC
Permalink
Post by David Bosschaert
When can we expect that JSR being formed? It's currently listed on
http://jcp.org/en/jsr/detail?id=337 as 'JSR TBD: Java Platform Module
System'.
I don't know, and the question is better directed to Oracle's JCP EC rep.

Alex
Eric Newcomer
2011-08-26 19:32:26 UTC
Permalink
Maybe I can find out from our JCP EC rep (Credit Suisse). I also keep asking about Oracle's plans to support the OSGi APIs in WebLogic similar to JBoss and WebSphere but it seems like we keep getting a similar story - Jigsaw is going to be in Java 8 and that's how our modularity requirements will be met, using a different type of "kitchen utensil" better suited for the job. But I still don't think the original question has ever really been answered about why Jigsaw could not have started with OSGi. What you always seem to get are these "difference of opinion" replies and "we are going ahead with what we're doing in OpenJDK anyway."

Eric

Sent from my iPad
Post by Alex Buckley
Post by David Bosschaert
When can we expect that JSR being formed? It's currently listed on
http://jcp.org/en/jsr/detail?id=337 as 'JSR TBD: Java Platform Module
System'.
I don't know, and the question is better directed to Oracle's JCP EC rep.
Alex
Alex Buckley
2011-06-28 23:30:38 UTC
Permalink
Post by David Bosschaert
I wonder why such a binary .class file for module declarations is
really needed. Why not go for a textual file, for instance
META-INF/module-info.jmod (or something like that) and declare the
module declarations in there using a textual format of some sort?
The arguments for a binary compiled form are given at:

http://openjdk.java.net/projects/jigsaw/doc/draft-java-module-system-requirements-12#_C
Post by David Bosschaert
IMO there are multiple benefits associated keeping the textual format.
People using the jar can use a simple zip tool to look inside the jar
to see what its dependencies are. Additionally tools can easily be
written to read the module-info.jmod file without needing to resort to
classfile parsing libraries. The module information can be of use to
both developer as well as deployer tools.
Finally it's probably easier to make the textual file extensible, as
required by [1], without resorting to inefficient reflection-style
operations.
I think these points are also captured in Appendix C. Could not the same
points have been made in favor of a textual format for class and
interface declarations?

Alex
Peter Kriens
2011-06-29 09:33:41 UTC
Permalink
I took a look at the proposal and I have a few comments. But first the picture (cardinalities are allowed by the structure but can be constrained in the text).




There seems to be quite a bit of redundancy (and thus complexity) in this structure because it allows * relations between the flags (provide,require,permit,module) that designate a ModuleId_Info struct. I.e. the proposal allows me to require/permit/provide the same module multiple times. Even though this is not allowed with an extraneous constraint this seems inefficient design, why create the opportunity for errors? It seems that provide/require/permit/module could easily be a handled with an enumeration or bitset: { THIS_MODULE, PROVIDE, PERMIT, REQUIRE_OPTIONAL, REQUIRE_FRAGMENT} in the ModuleId_Info struct? The use of attributes to set a bit seems overkill and will require unnecessary constraints on the cardinality of these attributes, making processing this file in tools harder.

Similar about the redundancy in the module name. The module name is both the this_class package name as well as defined in the ModuleId_Info struct?

Interestingly the model allows package export (though unfortunately not import, one should always wonder why things are not symmetric, but I guess that is another discussion). However, class exports can be top levels only (I assume no nested classes?) and recursively. However, packages are top level classes in the designated package and the all subpackages. This seems to miss the cases for nested classes in the single package and nested classes in the sub-packages?

I am a bit confused about the scope of the module as this is not defined. I.e. a class defines all its members, not just the public ones. Shouldn't a module also define its private members?

Obviously the extension model is a bit of a joke, all we get is a list of unadorned strings per module? The minimum that is needed is a model that allows the exports, provides, permits, and module attributes to be annotated in an elegant way. For example, ModuleClass is clearly a Jigsaw extension and several of the bit fields are also highly semantic, such semantics should be extensible as it is very unlikely you get it right the first time. Why not model these with an extension model and eat your own dog food?

The previous issues were detailed critiques on the design, intended to improve it within the box. However, I believe the premise of using attributes to model modules points to a serious problem with the box. Modularity is hierarchical, a function is modular, a type is modular, a package is modular, and this thing under construction is just the next granular step in modularity.

If a module is modeled as a class (as this design implicitly does by using the class file) then I think it should not introduce a completely new spaghetti ontology based on attributes but instead look at what the class file currently does, as a class is also modular. A class consists of a name, class or interface specific information, imports of other types, members, and conceptually nested types. So what is the member of a module? This is clearly the package. And the member of a package is clearly a Type. As members use other members, types import other types symmetry demands that packages import other packages and modules import other modules (as is done in the proposal with ModuleRequire).

Treating packages as members of a module and imports as references to other modules would make the class file a very good fit; every Java developer would immediately see the symmetry and have an intuitive understanding. Symmetry is one of the most important indicators that you've understood the problem and found the simplest model because it reuses existing concepts on different levels. For example, module extensions could now easily be modeled as standard annotations on members. It would also support module data/methods (static fields/methods in the module), as well as represent the Module Class implicitly.

Falling back to custom class attributes invariably means a huge amount of exceptional cases to handle by the community and makes it surprisingly hard to understand what's going on ...

As the current proposal has no affinity to a class file format whatsoever; it seems wrong to abuse the class file format just because it happens to support attributes. There are better formats for this purpose, formats that could also allow some human readability for debugging and easy annotation by third parties without requiring class format changes for every new module concept. Obviously XML is the most powerful and best suited format for this problem. The JLS module specification can just as easy output to XML as attributes in a class file but will be significantly easier to handle in most environments and will not require an upgrade in class version for every minor change.

Kind regards,

Peter Kriens









On Sat, Jun 25, 2011 at 3:01 AM, Alex Buckley <alex.buckley at oracle.com> wrote:
Since attachments seem to be scrubbed, here is the text of the proposal, obviously without links to the requirements document.


ClassFile changes for Java Modules

Binary form of a module declaration (a.k.a. module-info.class)
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 (0x0800), indicates that the ClassFile represents a module rather than a class or interface. Note that this flag plays a similar role to ACC_INTERFACE (0x0200), 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: >=52.0 (Java SE 8 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: 0
* 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, ModulePermits, ModuleExports, ModuleClass, 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.

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 module version.

CONSTANT_ModuleId_info {
u1 tag;
// 19
u2 name_index;
// Points to a CONSTANT_Utf8_info representing module name in internal form (JVMS 4.2.1)
u2 version_index;
// Optionally points to a CONSTANT_Utf8_info representing module version
}

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

If the version_index item is not 0, then a module version is present. There is no required structure or semantics for the underlying UTF8 string which represents a module version.

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 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.

The ModuleRequires attribute

ModuleRequires_attribute {

u2 attribute_name_index;
u4 attribute_length;
u2 requires_length;
{ u2 requires_index; u1 flags; } requires_table[requires_length];
}

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.
requires_length
The value of the requires_length indicates the number of entries in the requires_table.
requires_table
Each requires_index must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_ModuleId_info structure representing the target module on which this module depends.
The value of the associated flags item is as follows:

* 0x01 indicates this dependency on the target module is optional.
* 0x02 indictates the target module's types must be loaded by the same defining classloader as the types of the module represented by this ClassFile.

A module name may be referenced by at most one entry in a requires_table.

The ModulePermits attribute

ModulePermits_attribute {

u2 attribute_name_index;
u4 attribute_length;
u2 permits_length;
{ u2 permits_index } permits_table[permits_length];
}

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 "ModulePermits".
attribute_length
The value of the attribute_length item is the length of the attribute excluding the initial six bytes.
permits_length
The value of the permits_length indicates the number of entries in the permits_table.
permits_table
The value of each permits_index in this 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 representing a module which is permitted to have a dependency on the module represented by this ClassFile.
(It is possible that a module system uses only the name of the permitted module, not its version, in determining visibility.)
A module name may be referenced by at most one entry in a permits_table.

The ModuleProvides attribute

ModuleProvides_attribute {

u2 attribute_name_index;
u4 attribute_length;
u2 provides_length;
{ u2 provides_index; } provides_table[provides_length];
}

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.
provides_length
The value of the provides_length indicates the number of entries in the provides_table.
provides_table
The value of each provides_index in this 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 representing a module that is an alias for the module represented by this ClassFile.
A module name may be referenced by at most one entry in a provides_table.

The ModuleExports attribute

ModuleExports_attribute {

u2 attribute_name_index;
u4 attribute_length;
u2 exports_length;
{ u2 exports_index; u1 export_kind; u2 source_index; } exports_table[exports_length];
}

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 "ModuleExports".
attribute_length
The value of the attribute_length item is the length of the attribute excluding the initial six bytes.
exports_length
The value of the exports_length indicates the number of entries in the exports_table.
exports_table
The value of each export_index in this 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 an entity to be exported by the module represented by this ClassFile.
The value of the associated export_kind item indicates the kind of entity to be exported, as follows:

* 0x01 indicates the entity is a class or interface; it is the entity to be exported.
* 0x02 indicates the entity is a class or interface; it and its member types are the entities to be exported.
* 0x04 indicates the entity is a package; the member top-level classes and interfaces (and their member types) of this package are the entities to be exported.
* 0x08 indicates the entity is a package; the member top-level classes and interfaces (and their member types) of this package and all its subpackages (recursively) are the entities to be exported.

The value of the associated source_index item must be a valid index into the constant_pool table where the entry is a CONSTANT_ModuleId_info structure representing the module which declared the exported entity. (In most cases, where the exported entity is declared in the current module, source_index will simply point to the same constant pool entry as the Module attribute. But where the exported entity is re-exported, source_index may assist resolution and diagnostics.)

The ModuleClass attribute

ModuleClass_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 "ModuleClass".
attribute_length
The value of the attribute_length item is 2.
main_class_index
The value of the main_class_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 name of the class which is the entrypoint to the module represented by this ClassFile.

The ModuleData attribute

ModuleExtension_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 main_class 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 content, other than the module declaration, of the compilation unit that declared the module represented by this ClassFile.
Alex Buckley
2011-06-30 03:30:36 UTC
Permalink
Hi Peter,

Thanks for casting your eye over it.
Post by Peter Kriens
There seems to be quite a bit of redundancy (and thus complexity) in
this structure because it allows * relations between the flags
(provide,require,permit,module) that designate a ModuleId_Info
struct. I.e. the proposal allows me to require/permit/provide the
same module multiple times. Even though this is not allowed with an
extraneous constraint this seems inefficient design, why create the
opportunity for errors? It seems that provide/require/permit/module
could easily be a handled with an enumeration or bitset: {
THIS_MODULE, PROVIDE, PERMIT, REQUIRE_OPTIONAL, REQUIRE_FRAGMENT} in
the ModuleId_Info struct? The use of attributes to set a bit seems
overkill and will require unnecessary constraints on the cardinality
of these attributes, making processing this file in tools harder.
You'd still need a constraint that a (module id, enum value) pair must
be unique. Would that be extraneous too?

The use of multiple attributes is verbose, sure, but it's convenient for
prototyping.
Post by Peter Kriens
Similar about the redundancy in the module name. The module name is
both the this_class package name as well as defined in the
ModuleId_Info struct?
The reason for this is noted in the first section: there is
conventionally a mapping between pathname and this_class. The tiny
duplication is really not a big deal.
Post by Peter Kriens
Interestingly the model allows package export (though unfortunately
not import, one should always wonder why things are not symmetric,
but I guess that is another discussion). However, class exports can
be top levels only (I assume no nested classes?) and recursively.
However, packages are top level classes in the designated package and
the all subpackages. This seems to miss the cases for nested classes
in the single package and nested classes in the sub-packages?
There is nothing limiting an export to a top level class. "If you can
name it, you can export it."

(I should have said that exported entities are identified by binary
names, extended to allow package names, which have canonical names but
not binary names today.)

Not sure what you mean by "packages are top level classes in the
designated package". Both 0x04 and 0x08 for package export include
nested classes, in the same package and in subpackages respectively.
Post by Peter Kriens
I am a bit confused about the scope of the module as this is not
defined. I.e. a class defines all its members, not just the public
ones. Shouldn't a module also define its private members?
Since "private" (i.e. non-exported) classes are not visible from outside
the module, what difference would enumerating them make?
Post by Peter Kriens
Obviously the extension model is a bit of a joke, all we get is a
list of unadorned strings per module? The minimum that is needed is a
model that allows the exports, provides, permits, and module
attributes to be annotated in an elegant way. For example,
ModuleClass is clearly a Jigsaw extension and several of the bit
fields are also highly semantic, such semantics should be extensible
as it is very unlikely you get it right the first time. Why not model
these with an extension model and eat your own dog food?
The attributes follow the requirements of the Java Module System.
ModuleData is for content in a module declaration that is outside those
requirements. Regarding ModuleClass, it's a placeholder until there's a
requirement that addresses entrypoints.
Post by Peter Kriens
Treating packages as members of a module and imports as references to
other modules would make the class file a very good fit; every Java
developer would immediately see the symmetry and have an intuitive
understanding.
Package imports are an open requirement
(http://openjdk.java.net/projects/jigsaw/doc/draft-java-module-system-requirements-12#package-level-dependences)
so are not addressed here.
Post by Peter Kriens
As the current proposal has no affinity to a class file format
whatsoever; it seems wrong to abuse the class file format just
because it happens to support attributes. There are better formats
for this purpose, formats that could also allow some human
readability for debugging and easy annotation by third parties
without requiring class format changes for every new module concept.
Obviously XML is the most powerful and best suited format for this
problem. The JLS module specification can just as easy output to XML
as attributes in a class file but will be significantly easier to
handle in most environments and will not require an upgrade in class
version for every minor change.
Let's not argue about syntax ad infinitum. The big picture is that the
Java Module System will define a fixed set of "module concepts", as you
put it, whose semantics evolve at the pace of Java SE. New SE, new
classfile version, new module system constructs. Tools will evolve to
manage those constructs, as they do today for new language, VM, and API
features. For example, javadoc will render module dependencies.

Alex
mark.reinhold
2011-08-26 21:57:05 UTC
Permalink
Post by David Bosschaert
Reviving an old thread... it seems like this discussion is left
without coming to an agreed conclusion.
It's an issue where there are divergent views so I don't think you'll see
agreement here. For now, capturing the arguments in the requirements document
seems the right approach.
Right. As David says, the arguments for and against various schemes are very
well understood. OpenJDK Project Jigsaw is prototyping one scheme, but the
final choice of scheme is not up to the Project, it's up to the Expert Group of
the Java SE Module System JSR.
Exactly so.

FYI I expect to submit that JSR some time this October.

- Mark

Loading...