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:
./scripts/build-tauri-jlink.sh
Windows:
scripts\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