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
jdeps
to 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
jlink
workflows - 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
jlink
builds custom runtime images tailored to your app- Greatly reduces deployment size and improves performance
- Use
jdeps
to 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.