A common frustration Java developers face when deploying applications is shipping the entire JDK or JRE, even when their program uses only a fraction of the modules. This not only increases deployment size but also creates security risks by including unnecessary modules. With the Java Platform Module System (JPMS), introduced in Java 9, developers can leverage the jlink tool to build custom runtime images containing only the modules their applications require.
Think of this like packing for travel: instead of carrying your entire wardrobe, you carefully select only the clothes you’ll actually wear. jlink allows you to travel light in production, improving performance, security, and maintainability.
What is jlink?
jlink is a command-line tool included with the JDK that assembles and optimizes a set of modules into a custom runtime image. This runtime image looks like a stripped-down JRE, but it’s tailored specifically for your application.
Key benefits:
- Smaller runtime footprint
- Faster startup times
- Reduced attack surface by excluding unused modules
- Easy deployment without requiring a full JDK/JRE
Example: Creating a Custom Runtime Image
Step 1: Create a Modular Project
Suppose we have a module com.example.app that depends on java.sql:
module-info.java
module com.example.app {
requires java.sql;
}
Step 2: Compile the Module
javac -d out --module-source-path src $(find src -name "*.java")
Step 3: Run jlink
jlink --module-path $JAVA_HOME/jmods:out --add-modules com.example.app --output custom-runtime
This creates a custom-runtime/ directory containing the required runtime image.
Step 4: Run the Application
custom-runtime/bin/java -m com.example.app/com.example.app.Main
Best Practices & Pitfalls
✅ Best Practices
- Always verify module dependencies before linking
- Use
jdepsto analyze module usage - Include only what you need to minimize runtime size
- Automate runtime image creation in CI/CD pipelines
❌ Pitfalls
- Forgetting to include transitive dependencies → runtime errors
- Using automatic modules → reduces reliability of the image
- Attempting to run non-modular applications directly with
jlink
What's New in Java Versions?
- Java 5–8 → N/A (Modules introduced in Java 9)
- Java 9 → Introduction of JPMS and
jlink - Java 11 → Better tooling, long-term support for
jlinkworkflows - Java 17 → Security and performance improvements for modular builds
- Java 21 → No significant updates across Java versions for this feature
Real-World Analogy
Think of jlink as a meal prep kit: instead of buying an entire grocery store, you get only the pre-measured ingredients you need to cook one dish. This makes your life simpler, faster, and more efficient.
Summary & Key Takeaways
jlinkbuilds custom runtime images tailored to your app- Greatly reduces deployment size and improves performance
- Use
jdepsto analyze dependencies before linking - Avoid automatic modules when possible
- Perfect for microservices, containers, and embedded systems
FAQ: Using jlink
1. What is the difference between the classpath and module path?
Classpath loads everything blindly, while module path enforces module boundaries and visibility.
2. Why do I get “package is not visible” errors with modules?
Because JPMS enforces strong encapsulation — you must explicitly exports and requires.
3. What is the purpose of requires transitive?
It allows dependent modules to implicitly access transitive dependencies.
4. How do open and opens differ in reflection?open opens the whole module, while opens targets specific packages.
5. What are automatic modules, and should I use them?
JARs on the module path without module-info become automatic modules. They help migration but should not be used long-term.
6. How does JPMS improve security compared to the classpath?
By enforcing encapsulation and preventing accidental access to internal APIs.
7. When should I use jlink vs jmod?jmod packages modular artifacts, while jlink creates a full runtime image.
8. Can I migrate a legacy project to modules incrementally?
Yes, start with modularizing small components and using automatic modules as a bridge.
9. How do I handle third-party libraries that are not modularized?
Place them on the classpath or module path as automatic modules.
10. Do frameworks like Spring and Hibernate support modules?
Yes, but adoption varies. Many work well with modules but may need configuration.