What is the difference between a module with the open
keyword before it and without it? For instance:
open module foo {
}
module foo {
}
To set up a module, we need to put a special file at the root of our packages named module-info. java. This file is known as the module descriptor and contains all of the data needed to build and use our new module. We start the module declaration with the module keyword, and we follow that with the name of the module.
Defining the Java 9 module. A module is a collection of code, data, and resources. It is a set of related packages and types (classes, abstract classes, interfaces, and more) with code, data files, and some static resources. For example, the module descriptor module-info.
There is no need to switch to modules. There has never been a need to switch to modules. Java 9 and later releases support traditional JAR files on the traditional class path, via the concept of the unnamed module, and will likely do so until the heat death of the universe.
In order to provide reflective access to your module, Java 9 introduced the open keyword.
You can create an open module by using the open keyword in the module declaration.
An open module grants reflective access to all of its packages to other modules.
For example, if you want to use some framework that heavily relies on reflection, such as Spring, Hibernate, etc, you can use this keyword to enable reflective access for it.
You can enable reflective access for specified packages of your module by using the opens statement in the package declaration:
module foo {
opens com.example.bar;
}
or by using the open keyword in the module declaration:
open module foo {
}
but keep in mind, that you cannot combine them:
open module foo {
opens com.example.bar;
}
results with compile-time error.
Hope it helps.
A bit of a background to the directives in question. The Module System states in the Breaking encapsulation section
It is sometimes necessary to violate the access-control boundaries defined by the module system, and enforced by the compiler and virtual machine, in order to allow one module to access some of the unexported types of another module. This may be desirable in order to, e.g., enable white-box testing of internal types, or to expose unsupported internal APIs to code that has come to depend on them. The
--add-exports
option can be used, at both compile time and run time, to do this.
The command line option is equivalent to for example:-
module java.logging {
exports java.util.logging;
}
The --add-exports
option enables access to the public types of a specified package.
Though thereafter,
It is sometimes necessary to go further and enable access to all non-public elements via the setAccessible method of the core reflection API. The
--add-opens
option can be used, at runtime, to do this.
This command line option is equivalent to for example:-
module jdk.unsupported {
opens sun.misc;
}
An ordinary named module, by contrast, is defined explicitly with a module declaration as:-
module foo { }
and these are known as explicit modules. Explicit modules can use directives on packages as stated above for example to export
/open
packages to provide reflective access to their respective public members and classes.
On the other hand, an OPEN
module is a
module that does not declare any open packages but the resulting module is treated as if all packages are open.
Such that it grants access at runtime to types in all of the module's packages as if all packages are exported which means bytecode or reflection can be used to access every package's classes or members in all packages. The reflection APIs with setAccessible
or MethodHandles.privateLookupIn
allow for deep reflection, so in short you can reflect on all members of all classes in all packages. Which also pretty much explains the reason why compiler won't allow both open directives to a package while the module is already open.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With