6.4 KiB
JLink Runtime Bundling for Stirling-PDF
This guide explains how to use JLink to bundle a custom Java runtime with your Tauri application, eliminating the need for users to have Java installed.
Overview
Instead of requiring users to install a JRE separately, JLink creates a minimal, custom Java runtime that includes only the modules your application needs. This approach:
- Eliminates JRE dependency: Users don't need Java installed
- Reduces size: Only includes necessary Java modules
- Improves security: Minimal attack surface with fewer modules
- Ensures consistency: Same Java version across all deployments
Prerequisites
- JDK 17 or higher (not just JRE - you need
jlink
command) - Node.js and npm for the frontend
- Rust and Tauri CLI for building the desktop app
Quick Start
1. Build with JLink
Run the appropriate build script for your platform:
Linux/macOS:
./build-tauri-jlink.sh
Windows:
build-tauri-jlink.bat
2. Build Tauri Application
cd frontend
npm run tauri build
The resulting application will include the bundled JRE and won't require Java to be installed on the target system.
What the Build Script Does
- Builds the Stirling-PDF JAR using Gradle
- Analyzes dependencies using
jdeps
to determine required Java modules - Creates custom JRE using
jlink
with only necessary modules - Copies files to the correct Tauri directories:
- JAR file →
frontend/src-tauri/libs/
- Custom JRE →
frontend/src-tauri/runtime/jre/
- JAR file →
- Creates test launchers for standalone testing
Directory Structure
After running the build script:
frontend/src-tauri/
├── libs/
│ └── Stirling-PDF-X.X.X.jar
├── runtime/
│ ├── jre/ # Custom JLink runtime
│ │ ├── bin/
│ │ │ ├── java(.exe)
│ │ │ └── ...
│ │ ├── lib/
│ │ └── ...
│ ├── launch-stirling.sh # Test launcher (Linux/macOS)
│ └── launch-stirling.bat # Test launcher (Windows)
└── tauri.conf.json # Already configured to bundle runtime
Testing the Bundled Runtime
Before building the full Tauri app, you can test the bundled runtime:
Linux/macOS:
./frontend/src-tauri/runtime/launch-stirling.sh
Windows:
frontend\src-tauri\runtime\launch-stirling.bat
This will start Stirling-PDF using the bundled JRE, accessible at http://localhost:8080
Configuration Details
Tauri Configuration (tauri.conf.json
)
The bundle resources are configured to include both the JAR and runtime:
{
"bundle": {
"resources": [
"libs/*.jar",
"runtime/jre/**/*"
]
}
}
Gradle Configuration (build.gradle
)
JLink options are configured in the jpackage section:
jLinkOptions = [
"--strip-debug",
"--compress=2",
"--no-header-files",
"--no-man-pages"
]
addModules = [
"java.base",
"java.desktop",
"java.logging",
"java.management",
// ... other required modules
]
Rust Code (lib.rs
)
The application automatically detects and uses the bundled JRE instead of system Java.
Modules Included
The custom runtime includes these Java modules:
java.base
- Core Java functionalityjava.desktop
- AWT/Swing (for UI components)java.instrument
- Java instrumentation (required by Jetty)java.logging
- Logging frameworkjava.management
- JMX and monitoringjava.naming
- JNDI servicesjava.net.http
- HTTP clientjava.security.jgss
- Security servicesjava.sql
- Database connectivityjava.xml
- XML processingjava.xml.crypto
- XML securityjdk.crypto.ec
- Elliptic curve cryptographyjdk.crypto.cryptoki
- PKCS#11 supportjdk.unsupported
- Internal APIs (used by some libraries)
Troubleshooting
JLink Not Found
❌ jlink is not available
Solution: Install a full JDK (not just JRE). JLink is included with JDK 9+.
Module Not Found During Runtime
If the application fails with module-related errors, you may need to add additional modules to the addModules
list in build.gradle
.
Large Runtime Size
The bundled runtime should be 50-80MB. If it's much larger:
- Ensure
--strip-debug
and--compress=2
options are used - Review the module list - remove unnecessary modules
- Consider using
--no-header-files
and--no-man-pages
Benefits Over Traditional JAR Approach
Aspect | Traditional JAR | JLink Bundle |
---|---|---|
User Setup | Requires JRE installation | No Java installation needed |
Distribution Size | Smaller JAR, but requires ~200MB JRE | Larger bundle (~80MB), but self-contained |
Java Version | Depends on user's installed version | Consistent, controlled version |
Security Updates | User manages JRE updates | Developer controls runtime version |
Startup Time | May be faster (shared JRE) | Slightly slower (isolated runtime) |
Advanced Usage
Custom Module Analysis
To analyze your specific JAR's module requirements:
jdeps --print-module-deps --ignore-missing-deps build/libs/Stirling-PDF-*.jar
Manual JLink Command
If you want to create the runtime manually:
jlink \
--add-modules java.base,java.desktop,java.logging,java.management,java.naming,java.net.http,java.security.jgss,java.sql,java.xml,java.xml.crypto,jdk.crypto.ec,jdk.crypto.cryptoki,jdk.unsupported \
--strip-debug \
--compress=2 \
--no-header-files \
--no-man-pages \
--output frontend/src-tauri/runtime/jre
Migration Guide
From JAR-based Tauri App
- Update your Tauri configuration to include the runtime resources
- Update your Rust code to use the bundled JRE path
- Run the JLink build script
- Test the bundled runtime
- Build and distribute the new self-contained app
Deployment
The final Tauri application will be completely self-contained. Users can:
- Install the app normally (no Java installation required)
- Run the app immediately after installation
- Not worry about Java version compatibility issues
Support
If you encounter issues with the JLink bundling:
- Ensure you have a JDK (not JRE) installed
- Check that the Java version is 17 or higher
- Verify that the build script completed successfully
- Test the bundled runtime using the provided launcher scripts
- Check the Tauri build logs for any missing resources