如何缩小jpackage生成的Java可执行文件体积?
优化Java模块化Swing应用的jpackage打包体积
我有一个基于Java 22的模块化Swing项目(微软画图克隆程序),用jpackage生成的MSI安装包体积约70MB,但项目本身代码仅100KB,模块化Jar仅37KB。不需要安装程序,只需要能在Windows运行的可执行文件,目标体积小于10MB。
项目模块声明
module PaintModule { requires java.base; requires java.desktop; }
原createExecutable方法片段
private void createExecutable() throws Exception { System.out.println("STARTING TO RUN JPACKAGE"); final var jpackageCommand = java.util.spi.ToolProvider .findFirst("jpackage") .orElseThrow() ; final String executableName = prompt("Enter your executable name"); final String description = prompt("Enter the description for your executable"); jpackageCommand .run ( System.out, System.err, "--verbose", "--type", "msi", "--name", STR."\{executableName}", "--install-dir", STR."davidalayachew_applications/\{executableName}", "--vendor", "David Alayachew", "--module-path", STR."\{this.projectDirectory.resolve(Path.of("run", "executable", "jar")).toString()}", "--module", STR."\{this.moduleName}/\{this.packageName}.Main", "--win-console", "--win-dir-chooser", "--win-shortcut", "--win-shortcut-prompt", "--java-options", "--enable-preview", "--dest", STR."\{this.projectDirectory.resolve(Path.of("run", "executable", "installer")).toString()}", "--description", STR."\{description}" ); }
完整优化方案
核心思路
先通过jlink构建仅包含项目依赖的最小化JRE,再用jpackage基于这个定制JRE打包,避免包含完整JDK/JRE的冗余模块。
步骤1:新增定制JRE生成方法
在构建脚本中添加createCustomJre方法,生成精简版JRE:
private void createCustomJre() throws Exception { System.out.println("STARTING TO CREATE CUSTOM JRE WITH JLINK"); final var jlinkCommand = ToolProvider.findFirst("jlink").orElseThrow(); Path customJreDir = this.projectDirectory.resolve("run/executable/custom-jre"); // 清理旧的JRE目录 Files.walk(customJreDir) .sorted(Comparator.reverseOrder()) .map(Path::toFile) .forEach(File::delete); jlinkCommand.run( System.out, System.err, "--module-path", STR."\{this.projectDirectory.resolve("run/executable/jar")};\{System.getProperty("java.home")}/jmods", "--add-modules", this.moduleName, "--output", customJreDir.toString(), "--strip-debug", // 移除调试信息 "--no-man-pages", // 不包含手册文件 "--no-header-files", // 不包含头文件 "--compress=2" // 启用最高级别压缩 ); }
步骤2:修改jpackage命令逻辑
修改createExecutable方法,使用定制JRE并移除安装相关参数:
private void createExecutable() throws Exception { System.out.println("STARTING TO RUN JPACKAGE"); final var jpackageCommand = java.util.spi.ToolProvider .findFirst("jpackage") .orElseThrow() ; final String executableName = prompt("Enter your executable name"); final String description = prompt("Enter the description for your executable"); // 先生成定制JRE createCustomJre(); jpackageCommand .run ( System.out, System.err, "--verbose", "--type", "exe", // 直接生成独立exe,无需MSI安装包 "--name", STR."\{executableName}", "--module-path", STR."\{this.projectDirectory.resolve(Path.of("run", "executable", "jar")).toString()}", "--module", STR."\{this.moduleName}/\{this.packageName}.Main", "--runtime-image", STR."\{this.projectDirectory.resolve("run/executable/custom-jre")}", // 指定定制JRE路径 "--java-options", "--enable-preview", "--dest", STR."\{this.projectDirectory.resolve(Path.of("run", "executable", "standalone"))}", "--description", STR."\{description}" // 移除安装相关参数:--install-dir、--win-dir-chooser、--win-shortcut、--win-shortcut-prompt // 若不需要控制台窗口,可删除--win-console参数 ); }
额外优化建议
- 精简模块依赖:确认
module-info.java仅保留java.base和java.desktop,无多余依赖 - 移除预览特性:若项目不依赖预览API,删除
--enable-preview参数 - 验证Jar包内容:确保生成的模块化Jar仅包含必要的.class文件和清单,无冗余资源
预期效果
采用上述方案后,定制JRE体积约5-8MB,加上项目Jar和jpackage生成的exe,总体积可控制在10MB以内,完全满足目标。
内容的提问来源于stack exchange,提问作者davidalayachew
相关产品推荐
相关产品推荐

