Skip to main content
The jlink tool assembles and optimizes a set of modules and their dependencies into a custom runtime image. It is part of the jdk.jlink module.

Basic Usage

jlink [options] --module-path modulepath --add-modules module[,module...] --output path

Source Code

The jlink implementation is located at:
  • Main task: src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java:1
  • Task helper: src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java:1
  • Image builder: src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java:1

Required Options

--module-path
path
required
Path where the jlink tool discovers observable modules. Can also use -p.The path can be a directory containing module files or a module file itself. Multiple paths are separated by the platform-specific path separator (: on Linux/macOS, ; on Windows).
jlink --module-path $JAVA_HOME/jmods:mods \
      --add-modules com.example.app \
      --output myapp-runtime
--add-modules
module-list
required
Root modules to resolve in addition to the initial module. The modules must be found in the module path.
jlink --module-path $JAVA_HOME/jmods \
      --add-modules java.base,java.logging,java.sql \
      --output custom-jre
--output
path
required
Location of the generated runtime image. The directory must not already exist.
jlink --module-path mods \
      --add-modules myapp \
      --output dist/myapp-image

Module Selection Options

--limit-modules
module-list
Limit the universe of observable modules to those in the comma-separated list, plus the main module (if any), plus any further modules that these modules depend upon.
jlink --module-path $JAVA_HOME/jmods \
      --limit-modules java.base,java.logging \
      --add-modules java.logging \
      --output minimal-jre
--suggest-providers
module-name
Suggest providers that implement the given service type from the module path.
jlink --module-path $JAVA_HOME/jmods \
      --suggest-providers java.nio.file.spi.FileSystemProvider
--bind-services
none
Link service provider modules and their dependencies.
jlink --module-path $JAVA_HOME/jmods \
      --add-modules java.base \
      --bind-services \
      --output jre-with-services

Image Configuration

--launcher
name=module[/mainclass]
Add a launcher command of the given name for the module, and optionally the main class.
jlink --module-path mods \
      --add-modules com.example.app \
      --launcher myapp=com.example.app/com.example.app.Main \
      --output myapp-runtime

# Run with generated launcher
./myapp-runtime/bin/myapp
--endian
little|big
Byte order of the generated image (default: native).
jlink --module-path $JAVA_HOME/jmods \
      --add-modules java.base \
      --endian little \
      --output custom-jre
--ignore-signing-information
none
Suppress a fatal error when signed modular JARs are linked in the image. The signature-related files of the signed modular JARs are not copied to the runtime image.
jlink --module-path signed-mods \
      --add-modules com.example.signed \
      --ignore-signing-information \
      --output myapp

Output Control

--verbose
none
Enable verbose tracing. Can also use -v.
jlink -v --module-path mods \
      --add-modules myapp \
      --output dist/myapp
--save-opts
filename
Save jlink options in the specified file.
jlink --module-path mods \
      --add-modules myapp \
      --output myapp-runtime \
      --save-opts jlink.opts

Plugin Options

jlink includes a plugin system for customizing the generated image. Use --list-plugins to see available plugins.

compress

Compress resources in the output image.Level 0: No compression Level 1: Constant string sharing Level 2: ZIP compression
jlink --module-path $JAVA_HOME/jmods \
      --add-modules java.base \
      --compress 2 \
      --output compressed-jre

Common Usage Examples

Create Minimal Java Runtime

# Create runtime with only java.base module
jlink --module-path $JAVA_HOME/jmods \
      --add-modules java.base \
      --output minimal-jre

# Check size
du -sh minimal-jre

Create Application Runtime

# First, compile your modular application
javac -d mods/com.example.app \
      --module-source-path src \
      $(find src -name '*.java')

# Create runtime with your app and dependencies
jlink --module-path $JAVA_HOME/jmods:mods \
      --add-modules com.example.app \
      --launcher myapp=com.example.app/com.example.app.Main \
      --output myapp-runtime

# Run your application
./myapp-runtime/bin/myapp

Create Optimized Production Runtime

jlink --module-path $JAVA_HOME/jmods:mods \
      --add-modules com.example.app \
      --strip-debug \
      --compress 2 \
      --no-header-files \
      --no-man-pages \
      --launcher myapp=com.example.app/com.example.app.Main \
      --output myapp-prod

Create Cross-Platform Runtime

# Create Linux runtime from any platform
jlink --module-path linux-jmods:mods \
      --add-modules com.example.app \
      --launcher myapp=com.example.app \
      --output myapp-linux

Include Service Providers

jlink --module-path $JAVA_HOME/jmods:mods \
      --add-modules com.example.app \
      --bind-services \
      --output myapp-with-services

Advanced Options

--keep-packaged-modules
directory
Preserve packaged modules in the specified directory in the output image.
jlink --module-path mods \
      --add-modules myapp \
      --keep-packaged-modules jmods \
      --output myapp-runtime
--plugin-module-path
path
Custom plugin module path.
jlink --plugin-module-path custom-plugins \
      --module-path mods \
      --add-modules myapp \
      --output myapp-runtime

Information Options

--help
none
Print help message. Can also use -h or -?.
jlink --help
--version
none
Print version information.
jlink --version
--list-plugins
none
List available plugins.
jlink --list-plugins

Runtime Image Structure

The generated runtime image has the following structure:
myapp-runtime/
├── bin/              # Launcher scripts and executables
│   ├── java          # Java launcher
│   └── myapp         # Custom launcher (if --launcher used)
├── conf/             # Configuration files
│   ├── logging.properties
│   ├── net.properties
│   └── security/
├── legal/            # Legal notices
├── lib/              # Runtime libraries
│   ├── modules       # Optimized module image
│   ├── server/       # Server VM (if included)
│   └── *.so/*.dll    # Native libraries
└── release           # Release information
The modules file in the lib/ directory is a custom format optimized for fast module lookup and loading. It contains all the modules specified with --add-modules and their dependencies.
When using --launcher, jlink creates a native launcher that directly starts your application without requiring java -m modulename/mainclass. This provides a better user experience for standalone applications.

Plugin Development

Custom plugins can be created by implementing the jdk.tools.jlink.plugin.Plugin interface:
package com.example.jlink;

import jdk.tools.jlink.plugin.Plugin;
import jdk.tools.jlink.plugin.ResourcePool;
import jdk.tools.jlink.plugin.ResourcePoolBuilder;

public class CustomPlugin implements Plugin {
    @Override
    public String getName() {
        return "custom-plugin";
    }
    
    @Override
    public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
        // Transform resources
        in.entries().forEach(resource -> {
            // Process resource
            out.add(resource);
        });
        return out.build();
    }
}

Exit Codes

  • 0: Successful operation
  • 1: Errors occurred
  • 2: Invalid command-line arguments
  • 3: System error or resource exhaustion

See Also

Build docs developers (and LLMs) love