Working with Automatic Modules in JPMS

Illustration for Working with Automatic Modules in JPMS
By Last updated:

A common pain point for developers migrating legacy projects to the Java Platform Module System (JPMS) is dealing with third-party libraries that are not modularized. Without a module-info.java, these JARs cannot be used as named modules. Many developers mistakenly believe that such libraries are incompatible with JPMS.

The solution comes in the form of automatic modules. Automatic modules provide a bridge between the classpath and the module path, allowing non-modular JARs to behave like modules. However, overreliance on them can lead to fragile systems, unexpected dependencies, and maintenance issues.

In real-world enterprise applications, where frameworks like Spring, Hibernate, or older JDBC drivers are involved, automatic modules help ensure smooth incremental migration.

Think of automatic modules like temporary guest passes at a corporate office. Guests (non-modular libraries) can enter and interact, but without strict rules and contracts, security and governance may be compromised if they overstay.


What Are Automatic Modules?

  • Any JAR file placed on the module path without a module-info.java becomes an automatic module.
  • Automatic modules:
    • Export all packages by default
    • Implicitly require all other modules on the module path
    • Derive their names from the JAR file name

Example:

mylib-1.0.jar  →  module name: mylib

Example: Using Automatic Modules

Place a non-modular library JAR on the module path:

java --module-path mods:lib      -m com.example.app/com.example.app.Main

Automatic module inferred:

mylib-1.0.jar → module mylib

In module-info.java:

module com.example.app {
    requires mylib; // automatic module
}

Pitfalls of Automatic Modules

❌ Export all packages → breaks encapsulation
❌ Implicitly require all other modules → hidden dependencies
❌ Module names based on JAR filenames → unstable across versions
❌ Overreliance → delays proper modularization


Best Practices

✅ Use automatic modules only as transitional aids
✅ Gradually replace them with explicit modular JARs
✅ Define stable names with Automatic-Module-Name in MANIFEST.MF
✅ Document usage in CI/CD pipelines
✅ Keep track of transitive dependencies


Example: Defining Automatic-Module-Name

To avoid unstable module names, add to the JAR manifest:

Automatic-Module-Name: com.example.mylib

Migration Strategy with Automatic Modules

  1. Start by running non-modular libraries as automatic modules
  2. Add Automatic-Module-Name to stabilize names
  3. Replace with modular JARs over time
  4. Use tools like jdeps to analyze dependencies
  5. Aim for full explicit modularization

What's New in Java Versions?

  • Java 5–8 → N/A (no modules)
  • Java 9 → Introduction of JPMS, automatic modules as migration path
  • Java 11 → Wider adoption; Automatic-Module-Name became common practice
  • Java 17 → More stable ecosystem, fewer non-modular libraries
  • Java 21 → No significant updates across Java versions for this feature

Real-World Analogy

Automatic modules are like training wheels when learning to ride a bike. They help you transition, but keeping them forever prevents you from fully enjoying the efficiency and security of a modular system.


Summary & Key Takeaways

  • Automatic modules allow non-modular JARs to run on the module path
  • They export all packages and implicitly require all others
  • Use Automatic-Module-Name to stabilize names
  • Rely on them only temporarily; migrate to explicit modules
  • Tools like jdeps can guide migration

FAQ: Automatic Modules in JPMS

1. What is the difference between classpath and module path?
Classpath loads everything; module path enforces modular boundaries.

2. Why do I get “package is not visible” errors?
Because automatic modules export all packages, but visibility issues may arise if dependencies aren’t properly declared.

3. What is the purpose of requires transitive?
It propagates dependencies downstream, but automatic modules already imply all requires.

4. How do open and opens differ in automatic modules?
Automatic modules behave like open modules, exposing everything implicitly.

5. Should I use automatic modules in production?
Only as a temporary migration aid, not a long-term solution.

6. How does JPMS improve security compared to classpath?
It hides internal APIs unless explicitly exported, unlike automatic modules.

7. Should I use jlink or jmod with automatic modules?
Prefer explicit modules for custom runtimes; automatic modules reduce reliability.

8. Can I migrate legacy projects incrementally with automatic modules?
Yes, they are designed for step-by-step migration.

9. How do I handle third-party libraries that aren’t modularized?
Run them as automatic modules temporarily, or add Automatic-Module-Name.

10. Do frameworks like Spring and Hibernate work with automatic modules?
Yes, but they often require --add-opens flags for reflection-heavy features.