Java jar add module

Java Modules Cheat Sheet

Tell the compiler where to find your dependencies’ JARs:

—class-path, -cp $ Path to JARs, separated by : (🐧) or ; (⊞), e.g. —class-path libs/foo.jar:libs/bar.jar . Alternatively, add all JARs in a directory with —class-path ‘libs/*’ . —module-path, -p $ Like class path but with first-level support for directories: —module-path libs .

Usually, regular JARs go on the class path and modular JARs on the module path, but that’s not a hard rule.

—release $ Compile for a specific VM version. Supported targets: 6, 7, 8, 9, 10, 11 -source $ Provide source compatibility with specified release -target $ Generate class files for specific VM version —>

β‘‘ Source Files

Tell the compiler which source files to compile. There are various options:

  • Manually list all source files (possibly including module-info.java ), separated by space
  • Automatically determine all source files with `find $ -name *.java` (include backticks, replace $ with actual path; 🐧)
  • Use —source-path or —module-source-path (not covered here) Source Path —>

Archiver β€” jar

—create, -c Operation mode that creates an archive —file, -f $ The name of the JAR that will be created -C $ . Includes all files in directory $ (the trailing dot is important!)

Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ Ρ‚Π°ΠΊΠΆΠ΅:  Html ΠΊΠΎΠ΄Ρ‹ ΠΊΠΎΠ½Π΅Ρ† строки

If $ contains a module-info.class , the JAR will be modular.

β‘  More Options

Option of particular interest when packaging modules:

—main-class, -e $ Record the application entry point, i.e. the class with the main method

Virtual Machine β€” java

β‘  Path to JARs

Tell the compiler where to find your application’s JARs. Works exactly as during compilation, but remember to include your JARs.

β‘‘ More Options

Option of particular interest when running modules:

—show-module-resolution During JVM startup, log messages that show module resolution —illegal-access $ Define whether code in unnamed modules can use inaccessible types/members in named modules; $ can be permit , warn (default on Java 11), debug , or deny

β‘’ Main Module or Class

Tell the JVM how to launch the application. If the main class is on the class path:

If the main class is in a JAR on the module path:

General Options β€” javac , jar , java

@$ Read options and possibly filenames from file (only javac , java ), e.g. javac @opts @sources for files opts (containing all options) and sources (listing all source files) —help, -help, -?, -h / —help-extra, -X Print help text with all standard / non-standard tool options ( -h only on jar , java / -X only on javac , java ) —version, -version Print tool version

Recording Versions β€” javac , jar

The module system does not interpret module versions, but it can record them:

javac —module-version $ Embed the $ in the module declaration jar —module-version $ Embed the $ in the module declaration, possibly overriding the one embedded earlier by the compiler

At run time, the version of a module and its dependencies are available via ModuleDescriptor::requires .

Hacking the Module System β€” javac , java

—add-modules $ Add the $ and their dependencies to the module graph; use ALL-MODULE-PATH to add all modules from the module path —add-reads $=$ Make $ read the target modules; use ALL-UNNAMED as target to make the module read the class path —add-exports $/$=$ Let the $ access public types and members from $ ‘s $ —add-opens $/$=$ Let the $ access all types and members, regardless of visibility, from $ ‘s $ (only on java ) —patch-module $=$ Add classes from the $ to the $ , possibly overriding them

In some places you can specify more than one module. To do that, separate them with commas.

tags with directory trees * replace * «β–Έ» with «β–Έ» * «β–Ό» with «β–Ύ» —>

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ

Building Modules on the Command Line

When using the module system to create modules for your code, you will likely do that in a project that uses a build tool and so it is its task to get things right. But it helps tremendously to understand what «right» looks like and how to correctly configure javac , jar , and java to compile, package, and run your application. This will give you a better understanding of the module system and help debug problems in case the build tool doesn’t get it right.

Note: You need to know the module system basics to get the most out of this article. You may also want to check out the description of the core JDK tools.

A Basic Build

Given a project with a few source files, a module declaration, and a few dependencies, this is how you can compile, package, and run it in the simplest way:

# compile sources files, including module-info.java $ javac --module-path $DEPS -d $CLASS_FOLDER $SOURCES # package class files, including module-info.class $ jar --create --file $JAR $CLASSES # run by specifying a module by name $ java --module-path $JAR:$DEPS --module $MODULE_NAME/$MAIN_CLASS 

There’s a bunch of placeholders in there:

  • $DEPS is the list of dependencies. These are typically paths to JAR files separated by : (Unix) or ; (Windows), but on the module path, this can also just be folder names (without the /* -trickery that’s required on the class path).
  • $CLASS_FOLDER is the path to the folder where the *.class files will be written to.
  • $SOURCES is the list of *.java files and must include module-info.java .
  • $JAR is the path to the JAR file that will be created.
  • $CLASSES is the list of *.class files that was created during compilation (thus found in $CLASS_FOLDER ) and must include module-info.class .
  • $MODULE_NAME/$MAIN_CLASS is the name of the initial module (i.e. the one where module resolution starts) followed by the name of the class containing the app’s main method.

For a simple «Hello World» style project with the common src/main/java structure, just a single source file, dependencies in a deps folder, and using Maven’s target folder that would look as follows:

$ javac --module-path deps -d target/classes src/main/java/module-info.java src/main/java/com/example/Main.java $ jar --create --file target/hello-modules.jar target/classes/module-info.class target/classes/com/example/Main.class $ java --module-path target/hello-modules.jar:deps --module com.example/com.example.Main 

Defining a Main Class

The jar option —main-class $MAIN_CLASS embeds $MAIN_CLASS as the class containing the main method in the module descriptor, which allows you to launch a module without having to name the main class:

$ jar --create --file target/hello-modules.jar --main-class com.example.Main target/classes/module-info.class target/classes/com/example/Main.class $ java --module-path target/hello-modules.jar:deps --module com.example 

Note that it is possible to override that class and launch another, simply by naming it as before:

# create a JAR with `Main` and `Side`, # making `Main` the main class $ jar --create --file target/hello-modules.jar --main-class com.example.Main target/classes/module-info.class target/classes/com/example/Main.class target/classes/com/example/Side.class # override the main class and launch `Side` $ java --module-path target/hello-modules.jar:deps --module com.example/com.example.Side 

Circumventing Strong Encapsulation

The module system is very strict about access to internal APIs: If the package isn’t exported or opened, access will be denied. But a package can’t just be exported or opened by a module’s author — there are also the command line flags —add-exports and —add-opens , which allow the module’s user to do that as well.

As an example, see this code that tries to create an instance of the internal class sun.util.BuddhistCalendar :

BuddhistCalendar calendar = new BuddhistCalendar(); 

To compile and run it, we need to use —add-exports :

javac --add-exports java.base/sun.util=com.example.internal module-info.java Internal.java # package with `jar` java --add-exports java.base/sun.util=com.example.internal --module-path com.example.internal.jar --module com.example.internal 

If the access is reflective.

Class.forName("sun.util.BuddhistCalendar").getConstructor().newInstance(); 

. compilation will work without further configuration, but we need to add —add-opens when running the code:

java --add-opens java.base/sun.util=com.example.internal --module-path com.example.internal.jar --module com.example.internal 

Extending the Module Graph

Starting with an initial set of root modules, the module system computes all of their dependencies and builds a graph, where the modules are nodes and their readability relations are directed edges. This module graph can be extended with the command line flags —add-modules and —add-reads , which add modules (and their dependencies) and readability edges, respectively.

As an example, let’s imagine a project that has an optional dependency on java.sql, but the module is not otherwise required. That means it’s not added to the module graph without a little help:

# launch without java.sql $ java --module-path example.jar:deps --module com.example/com.example.Main # launch with java.sql $ java --module-path example.jar:deps --add-modules java.sql --module com.example/com.example.Main 

An alternative approach to optional dependencies would be to not list the dependency at all and only add it with —add-modules and —add-reads (this is rarely helpful and not generally recommended — just an example):

$ java --module-path example.jar:deps --add-modules java.sql --add-reads com.example=java.sql --module com.example/com.example.Main 

Specify version of modules that are being compiled —patch-module = (: )* Override or augment a module with classes and resources in JAR files or directories —upgrade-module-path

Override location of upgradeable modules —>

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ

ΠžΡ†Π΅Π½ΠΈΡ‚Π΅ ΡΡ‚Π°Ρ‚ΡŒΡŽ