Java Modules Cheat Sheet

A cheat sheet for building and running Java modules from the command line with javac, jar, and java

Compiler — javac

	${path_to_deps} ①
	-d ${class_dir}
	${source_files} ②
-d ${class_dir}
Directory for generated class files

① Path to Dependencies

Tell the compiler where to find your dependencies' JARs:

--class-path, -cp ${path}
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 ${path}
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.

② Source Files

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

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

Archiver — jar

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

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

① More Options

Option of particular interest when packaging modules:

--main-class, -e ${main_class}
Record the application entry point, i.e. the class with the main method

Virtual Machine — java

	${path_to_jars} ①
	${more_options} ②
	${main} ③

① 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:

During JVM startup, log messages that show module resolution
--illegal-access ${value}
Define whether code in unnamed modules can use inaccessible types/members in named modules; ${value} 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:

  • Fully qualified name of the main class

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

  • --module ${module} if jar recorded ${module}'s main class
  • --module ${module}/{main_class} to specify or override ${module}'s main class

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 ${version}
Embed the ${version} in the module declaration
jar --module-version ${version}
Embed the ${version} 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 ${modules}
Add the ${modules} and their dependencies to the module graph; use ALL-MODULE-PATH to add all modules from the module path
--add-reads ${module}=${target_modules}
Make ${module} read the target modules; use ALL-UNNAMED as target to make the module read the class path
--add-exports ${module}/${package}=${target_modules}
Let the ${target_modules} access public types and members from ${module}'s ${package}
--add-opens ${module}/${package}=${target_modules}
Let the ${target_modules} access all types and members, regardless of visibility, from ${module}'s ${package} (only on java)
--patch-module ${module}=${jar_files}
Add classes from the ${jar_files} to the ${module}, possibly overriding them

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

image/svg+xml ▸ classes▸ jars▾ libs greetings-framework-v2.4.1.jar▾ src ▾ org ▾ codefx ▾ classes ▾ org ▾ codefx HelloWorld.class module-info.class▸ jars▸ libs▸ src ▸ classes▾ jars hello.jar▾ libs greetings-framework-v2.4.1.jar▸ src Compiler — javac javac --class-path 'libs/*' -d classes src/org/codefx/ javac --module-path libs -d classes src/org/codefx/ src/ Archiver — jar jar --create --file jars/hello.jar -C classes . jar --create --file jars/hello.jar --main-class org.codefx.HelloWorld -C classes . Virtual Machine — java java --class-path 'libs/*':'jars/*' org.codefx.HelloWorld java --module-path libs:jars --module org.codefx.hello 011011010101

First of all, in case you're looking at this on mobile, I'm sorry that the diagram is unreadable - I haven't figured out the art of responsive diagrams yet. 😔

Other than that, I hope you like this sheet and it helps you, should you ever need to build a module by hand. Why you would need to do that? Because building modules from the command line is the best way to get to know them. So if you're learning what Java's module system has to offer, I recommend putting your build tool aside for a day and go old-school.