基于Maven的Java控制台应用如何与完整JRE打包?
Hey there! I’ve helped tons of folks solve exactly this problem—packaging a Maven-managed Java console app (with all dependencies bundled into a fat JAR) along with a JRE so it runs on machines without pre-installed Java. You mentioned trying javapackager -deploy and hitting issues, so let’s break down fixes for that approach, plus some better modern alternatives that might save you time.
First: Double-Check Your Fat JAR Setup
Before diving into packaging, make sure your maven-assembly-plugin is correctly configured to build a runnable fat JAR with your main class specified. Here’s a solid baseline config for your pom.xml:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.6.0</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.yourpackage.YourMainClass</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>build-fat-jar</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
Run mvn package and verify the fat JAR in target/ runs with java -jar your-app-jar-with-dependencies.jar before moving on.
Fixing the javapackager Approach
If you’re set on using javapackager, the most common issues are incorrect parameters or missing JRE references. Here’s the correct command structure, tailored to your setup:
javapackager -deploy \ -native image \ -srcdir target \ -srcfiles your-app-jar-with-dependencies.jar \ -appclass com.yourpackage.YourMainClass \ -outdir deploy \ -outfile YourAppName \ -v
Key Parameter Breakdown:
-native image: Generates a standalone native app bundle (adjust toexe/msifor Windows,dmgfor Mac,deb/rpmfor Linux)-srcdir: Points to the directory containing your fat JAR-appclass: Full qualified name of your main class (matches what’s in the fat JAR manifest)-v: Verbose mode—critical for debugging why the command fails (look for errors like missing main class or JRE path issues)
Common Fixes for javapackager Errors:
- JRE Not Found: If
javapackagercan’t locate a JRE, add-Bruntime=/path/to/your/full-jreto specify a custom JRE directory - Main Class Mismatch: Double-check that
-appclassmatches the main class in your fat JAR’s manifest (runjar xf your-fat-jar.jar META-INF/MANIFEST.MFto verify) - System Compatibility:
javapackagerbuilds bundles for the OS it’s run on—so build on Windows for Windows exe, Mac for Mac dmg, etc.
Modern Alternative: Use jpackage (Java 14+)
javapackager was deprecated in Java 14 and replaced with jpackage, which is more robust and easier to use. It supports both full and trimmed JREs (to reduce bundle size).
Step 1: Create a Trimmed JRE (Optional but Recommended)
Use jlink to create a minimal JRE containing only the modules your app needs (cuts down bundle size significantly):
jlink \ --module-path $JAVA_HOME/jmods \ --add-modules java.base,java.logging,java.io \ # Add modules your app uses --output custom-jre \ --strip-debug \ --compress 2 \ --no-header-files \ --no-man-pages
Step 2: Package with jpackage
Run this command to bundle your fat JAR with the trimmed (or full) JRE:
jpackage \ --name YourAppName \ --input target \ --main-jar your-app-jar-with-dependencies.jar \ --main-class com.yourpackage.YourMainClass \ --runtime-image custom-jre \ # Use the trimmed JRE we created --type app-image \ # Or "exe", "msi", "dmg", "deb" depending on OS --arguments "%*" # Pass command-line arguments to your app
This will generate a standalone app bundle in a new directory—users can just run the executable and pass command-line args like normal.
Automate Everything with Maven Plugins
To avoid running manual commands every time, integrate jpackage directly into your Maven build using the official maven-jpackage-plugin. Add this to your pom.xml after the maven-assembly-plugin config:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jpackage-plugin</artifactId> <version>1.0.0</version> <executions> <execution> <phase>package</phase> <goals> <goal>jpackage</goal> </goals> </execution> </executions> <configuration> <name>YourAppName</name> <inputDirectory>${project.build.directory}</inputDirectory> <mainJar>${project.build.finalName}-jar-with-dependencies.jar</mainJar> <mainClass>com.yourpackage.YourMainClass</mainClass> <runtimeImage>custom-jre</runtimeImage> <!-- Path to your trimmed JRE --> <type>app-image</type> <arguments>%*</arguments> </configuration> </plugin>
Now just run mvn package and Maven will build the fat JAR, then package it with the JRE automatically.
For Windows Users: launch4j-maven-plugin
If you specifically need a Windows .exe that bundles the JRE, the launch4j plugin is a tried-and-true option. Add this to your pom.xml:
<plugin> <groupId>com.akathist.maven.plugins.launch4j</groupId> <artifactId>launch4j-maven-plugin</artifactId> <version>2.2.0</version> <executions> <execution> <id>build-windows-exe</id> <phase>package</phase> <goals> <goal>launch4j</goal> </goals> <configuration> <headerType>console</headerType> <!-- Important for console apps --> <outfile>target/YourApp.exe</outfile> <jar>${project.build.finalName}-jar-with-dependencies.jar</jar> <jre> <path>jre/</path> <!-- Place your JRE in target/jre/ --> <minVersion>1.8.0</minVersion> </jre> <cmdLineArgs>%*</cmdLineArgs> <!-- Pass command-line args --> </configuration> </execution> </executions> </plugin>
Copy your JRE into target/jre/, run mvn package, and you’ll get an .exe that uses the bundled JRE—no pre-installed Java needed.
内容的提问来源于stack exchange,提问作者Mattizin

