Working with Java Modules (JPMS)

1. Understanding module-info.java

ElementPurpose
module name { ... }Declare module
LocationRoot of source tree
Compiled tomodule-info.class
Java version9+

Example: module-info.java

module com.acme.app {
    requires java.net.http;
    requires transitive com.acme.api;
    exports com.acme.app.public.api;
    opens com.acme.app.dto to com.fasterxml.jackson.databind;
    provides com.acme.spi.Greeter with com.acme.app.HelloGreeter;
    uses com.acme.spi.Greeter;
}

2. Using requires Directive

FormEffect
requires MCompile + runtime dep
requires static MCompile-only (optional at runtime)
requires transitive MRe-export to consumers

3. Using exports Directive

FormEffect
exports pPublic API for all
DefaultPackages are NOT exported
GranularityPer-package (not per-class)

4. Using opens Directive

FormEffect
opens pAllow deep reflection at runtime
open module MOpen all packages
vs exportsopens enables setAccessible(true)
UseFrameworks (Jackson, Hibernate, JPA)

5. Using Qualified Exports

FormEffect
exports p to M1, M2Only listed modules see it
opens p to M1Reflective access only to M1
UseFriend modules / internal sharing

6. Using requires transitive

EffectDetail
Implied readabilityConsumers of A see B's exports
UseAggregator modules, API surface re-export
Examplejava.sql → requires transitive java.logging

7. Using provides and uses (ServiceLoader)

DirectiveUse
uses SConsumer declares need
provides S with ImplProvider supplies impl
LookupServiceLoader.load(S.class)

8. Creating Modular JARs

StepCommand
Compilejavac -d out/M --module-source-path src $(find src -name "*.java")
Packagejar --create --file mods/M.jar -C out/M .
Main classjar ... --main-class com.acme.Main

9. Using --module-path

FlagUse
--module-path / -pWhere to find modules
--module / -mRun main of module
--add-modulesInclude extra root modules
--add-opensRuntime open (for legacy reflection)
--add-readsForce read edge

10. Working with Automatic Modules

AspectDetail
SourcePlain JAR placed on module-path
NameFrom Automatic-Module-Name manifest or filename
ReadsAll other modules
ExportsAll packages
UseMigration bridge for non-modular libs

11. Migrating Legacy Code to Modules

Migration Steps

  1. Run on classpath as unnamed module — verify behavior
  2. Place dependencies on module-path → automatic modules
  3. Add module-info.java to your code (top-down)
  4. Resolve split-packages and JDK internal usage
  5. Convert dependencies to explicit modules
IssueFix
Split packagesRefactor or merge
sun.misc.UnsafeMigrate to VarHandle / Foreign Memory
ReflectionAdd --add-opens or open module

12. Using jdeps for Module Analysis

CommandUse
jdeps lib.jarShow dependencies
jdeps --jdk-internals lib.jarDetect internal API use
jdeps --generate-module-info ./out lib.jarGenerate stub module-info
jdeps -s lib.jarSummary only