JDK jpackage 详解:从官方手册到源码实现,掌握 Java 自包含应用与原生安装包打包 JDK jpackage 详解从官方手册到源码实现掌握 Java 自包含应用与原生安装包打包【免费下载链接】jdkJDK main-line development https://openjdk.org/projects/jdk项目地址: https://gitcode.com/GitHub_Trending/jd/jdkjpackage 是 JDK 中用于把 Java 应用连同 Java 运行时一起打包为自包含应用图像application image或平台原生安装包Windows 的 exe/msi、Linux 的 rpm/deb、macOS 的 pkg/dmg的核心命令行工具。本文基于 JDK 仓库中 jpackage 的官方手册页 jpackage.md 逐节展开覆盖全部通用选项、运行时图像选项、启动器选项、平台相关选项与资源目录定制机制并对照jdk.jpackage模块的真实源码CLI 解析、模型类、原生启动器说明这些选项在实现中是如何生效的帮助读者既能照着手册打包发布也能在定制模板、排查打包问题时深入源码定位。一、jpackage 在 JDK 工具链中的定位手册页对 jpackage 的定义是以 Java 应用和 Java 运行时图像为输入生成包含所有必要依赖的自包含 Java 应用图像并能进一步产出平台特定格式的原生安装包例如 Windows 上的exe、macOS 上的dmg。有两个关键约束必须牢记不支持跨平台构建每种格式都必须在它所运行的平台上构建build on the platform it runs on输入是应用 运行时两要素应用可以是模块或 JAR运行时图像通常由 jpackage 内部调用 jlink 生成见第三节。从源码结构看jpackage 的实现分层清晰入口在 Main.java命令行解析由jdk.jpackage.internal.cli包完成Options.java、OptionsProcessor、StandardOption 等解析结果沉淀到jdk.jpackage.internal.model包的模型对象Application.java、BundleSpec.java而最终生成的可执行启动器则由 C/C 原生代码实现核心文件是 JvmLauncher.cpp 与 CfgFile.cpp按平台分别位于 LinuxLauncher.c、MacLauncher.cpp 和src/jdk.jpackage/windows/native/applauncher/WinLauncher.cpp。包类型本身在 PackageType.java 中定义为一个non-sealed interface继承自BundleType各平台的 dmg、rpm、msi 等类型都实现该接口——这与手册中--type的取值一一对应。二、命令概要与通用选项用法概要为jpackage [options]options为以空格分隔的命令行选项全部选项按功能划分为四组通用选项、创建运行时图像选项、创建应用图像选项、创建启动器选项含平台相关子集。以下按手册的分组完整列出。2.1 通用选项选项说明filename从文件读取选项可多次使用--type/-t type指定创建的包类型--app-version version应用和/或包的版本--copyright copyright应用的版权声明--description description应用的描述--help/-h打印当前平台全部合法选项的用法文本后退出--icon path应用包图标路径绝对路径或相对当前目录--name/-n name应用和/或包名称--dest/-d destination生成输出文件放置的路径默认为当前工作目录--resource-dir path用于覆盖 jpackage 内置资源图标、模板文件等的目录--temp directory指定一个新建或为空的目录存放临时文件指定后任务结束时不会自动删除需手动清理不指定则自动创建并在任务完成后删除--vendor vendor应用供应商--verbose [-,key(,[-]key)*]配置冗长输出详见 2.2--version打印产品版本后退出其中--type的合法取值为{app-image, exe, msi, rpm, deb, pkg, dmg}。若未指定--typejpackage 会创建平台相关的默认类型——即 Windows 上默认为 exe 系安装包、Linux 上为 deb/rpm、macOS 上为 dmg/pkg具体由当前主机平台决定。2.2--verbose的日志类别控制--verbose通过逗号分隔的键组合来启用/禁用日志消息类别前缀-表示禁用。支持的键及其含义all启用所有类别的控制台输出并通过 System.Logger API 路由到日志框架等价于console,logconsole启用所有类别的控制台输出等价于all,-logerrors输出致命错误。不带trace时错误信息不含异常堆栈带trace时附带堆栈progress输出进度消息resources输出关于可配置资源使用情况的消息summary输出包属性以及所用工具的版本信息tools输出正在执行的命令。不带trace时只打印与包定制相关的命令行不打印其执行输出带trace时打印所有命令行及其输出trace输出被抑制异常的堆栈和 jpackage 执行细节与其他键组合时为对应类别的消息附加额外信息warning输出警告log将所有消息类别通过 System.Logger API 路由到日志框架日志器名称为jdk.jpackage。默认行为--verbose不带值时等价于--verbose console,-trace完全不指定该选项时等价于--verbose errors,warnings。手册给出的典型用法# 关闭全部控制台输出只通过 System.Logger API 记录日志 --verbose log # 在控制台启用所有消息类别 --verbose console # 启用所有类别但排除 trace 和 tools --verbose console,-trace,-tools # 在控制台启用 trace 和 tools 类别 --verbose trace,tools # 同时启用 trace/tools 控制台输出与日志框架路由 --verbose log,trace,tools2.3 创建运行时图像的选项选项说明--add-modules module-name[,...]要添加的模块列表逗号分隔连同主模块一起作为 jlink 的--add-modules参数未指定时仅链接主模块指定了--module时或默认模块集指定了--main-jar时。可多次使用--module-path/-p module-path[,...]以File.pathSeparator分隔的路径列表每项是一个模块目录或模块化 jar绝对路径或相对当前目录。可多次使用--jlink-options options传给 jlink 的空格分隔选项列表。未指定时默认为--strip-native-commands --strip-debug --no-man-pages --no-header-files。可多次使用--runtime-image directory预定义运行时图像的路径将直接复制到应用图像中不指定时 jpackage 运行 jlink 并按--jlink-options创建运行时图像2.4 创建应用图像的选项--input/-i directory包含待打包文件的输入目录目录中所有文件都会被打包进应用图像--app-content additional-content[,...]添加到应用载荷payload中的文件或目录路径列表逗号分隔可多次使用。--app-content在--app-resources之后处理与命令行顺序无关。macOS 注意其值应是带有Resources子目录或应用包Contents目录中其他合法目录的目录否则可能产出无效的 bundle 导致代码签名和/或公证失败--app-resources additional-resources添加到应用资源目录中的文件或目录路径列表分隔符为平台路径分隔符Linux 和 macOS 为:Windows 为;可多次使用。与--app-content冲突的文件以--app-content一方为准。资源落位路径因平台而异Windows应用图像根目录Linux应用图像的 lib 目录macOSContents/Resources2.5 创建应用启动器的选项选项说明--module/-m module-name[/main-class]应用的主模块可选指定主类该模块必须位于模块路径上指定后会链接进 Java 运行时图像。与--main-jar互斥--main-jar main-jar应用主 JAR相对输入路径的路径含主类。与--module互斥--main-class class-name应用主类的限定名仅在指定了--main-jar时可用--java-options options传给 Java 运行时的选项可多次使用值支持运行时替换规则同--arguments--arguments arguments启动器未收到命令行参数时传给主类的参数可多次使用值支持运行时替换详见下--add-launcher namepath构建附加替代启动器启动器名 一个 Properties 文件路径--arguments/--java-options的运行时替换规则这是启动器原生实现的细节见 JvmLauncher.cpp值中可以包含运行时展开的子串支持两类环境变量和APPDIR、BINDIR、ROOTDIR令牌可展开子串需以$与其后第一个非字母数字字符之间界定或用${与}界定环境变量名在 Unix 上区分大小写在 Windows 上不区分若引用的环境变量未定义则不发生任何字符串展开名为APPDIR、BINDIR、ROOTDIR的环境变量会被忽略这些子串由应用启动器计算出的值替换在$前加反斜杠\$可阻止展开。--add-launcher的 Properties 文件中可用的键为module、main-jar、main-class、description、arguments、java-options、icon、launcher-as-service、win-console、win-shortcut、win-menu、linux-shortcut。这些键会追加或覆盖原始命令行选项从而构建额外的替代启动器主应用启动器始终由命令行选项构建该选项可多次使用以构建多个附加启动器。平台相关启动器选项Windows仅在 Windows 上可用--win-console——创建带控制台的启动器适用于需要控制台交互的应用macOS仅在 macOS 上可用--mac-package-identifier identifier唯一标识应用的包标识符默认为主类名只允许字母数字、连字符和点--mac-package-name name应用栏Menu Bar中显示的名称可不同于应用名须短于 16 个字符默认为应用名--mac-package-signing-prefix prefix签名时为没有既有包标识符的组件添加前缀--mac-sign请求对包或预定义应用图像进行签名--mac-signing-keychain keychain-name查找签名身份所用钥匙串的名称未指定则使用标准钥匙串--mac-signing-key-user-name nameApple 签名身份中的团队或用户名部分--mac-app-store表明输出面向 Mac App Store--mac-entitlements path签名 bundle 内可执行文件和库时使用的 entitlements 文件路径--mac-app-category category用于构建应用 plist 中LSApplicationCategoryType的字符串默认值为utilities。2.6 创建应用包的选项选项说明--about-url url应用主页 URL--app-image directory预定义应用图像的位置用于构建可安装包所有平台或在 macOS 上用于签名--file-associations path包含键值对的 Properties 文件路径可用键为extension、mime-type、icon、description可多次使用--install-dir path应用安装目录的绝对路径macOS 或 Linux或安装目录的相对子路径Windows如Program Files、AppData--license-file path许可证文件路径--runtime-image path要安装的预定义运行时图像路径创建运行时安装包runtime installer时必选--launcher-as-service请求创建安装器将主应用启动器注册为后台服务类型应用2.7 平台相关的包选项Windows 平台仅在 Windows 上可用选项说明--win-dir-chooser添加对话框让用户选择产品安装目录--win-help-url url用户获取更多信息或技术支持的 URL--win-menu为应用添加开始菜单快捷方式若指定了--win-shortcut-prompt则改为请求用户确认--win-menu-group menu-group-name应用被放入的开始菜单组--win-per-user-install按用户per-user安装不带此选项则按机器per-machine安装--win-shortcut为应用添加桌面快捷方式行为同--win-menu--win-shortcut-prompt当至少指定了--win-menu或--win-shortcut时添加对话框让用户选择是否创建这些快捷方式--win-update-url url应用更新信息可用处的 URL--win-upgrade-uuid id与该包升级关联的 UUID--win-with-ui强制安装器带有 UILinux 平台仅在 Linux 上可用选项说明--linux-package-name nameLinux 包名默认与应用名相同--linux-deb-maintainer email-address.deb 包的维护者--linux-menu-group menu-group-name应用被放入的菜单组--linux-package-deps package-dep-string应用所需的包或能力capabilities--linux-rpm-license-type type许可证类型对应 RPM .spec 中的License: value--linux-app-release releaseRPMname.spec文件的 Release 值或 DEB control 文件的 Debian revision 值--linux-app-category category-valueRPMname.spec文件的 Group 值或 DEB control 文件的 Section 值--linux-shortcut为应用创建快捷方式macOS 平台仅在 macOS 上可用--mac-dmg-content additional-content[,...]将引用的内容全部包含进 dmg可多次使用。三、实战命令示例手册给出的完整示例覆盖五种典型场景均可直接复制使用1. 生成适合宿主系统的应用安装包# 模块化应用 jpackage -n name -p modulePath -m moduleName/className # 非模块化应用 jpackage -i inputDir -n name \ --main-class className --main-jar myJar.jar # 从已构建好的应用图像出发 jpackage -n name --app-image appImageDir2. 生成应用图像app-image# 模块化应用 jpackage --type app-image -n name -p modulePath \ -m moduleName/className # 非模块化应用 jpackage --type app-image -i inputDir -n name \ --main-class className --main-jar myJar.jar # 需要自定义 jlink 选项时单独运行 jlink jlink --output appRuntimeImage -p modulePath \ --add-modules moduleName \ --no-header-files [additional jlink options...] jpackage --type app-image -n name \ -m moduleName/className --runtime-image appRuntimeImage3. 生成 Java 运行时安装包jpackage -n name --runtime-image runtime-image4. 在 macOS 上对预定义应用图像进行签名jpackage --type app-image --app-image app-image \ --mac-sign [additional signing options...]注意在此模式下唯一允许的其他选项是 mac 签名选项集合和--verbose。四、jpackage 与 jlink 的关系jpackage 除非使用了--runtime-image否则都会调用 jlink 创建 Java 运行时。一个与平台相关的细节是在 Windows 上jpackage 创建的 Java 运行时图像会包含 JDK 捆绑的 MS 运行时库MS runtime libraries如果应用需要不同版本的 MS 运行时库用户需要自行添加或替换。默认 jlink 参数--strip-native-commands --strip-debug --no-man-pages --no-header-files说明 jpackage 默认追求精简运行时剥离原生命令、调试信息与头文件。若你的应用依赖jpackage、jlink等 JDK 命令行工具二进制或调试符号应通过--jlink-options显式覆盖或按第三节的示例单独运行 jlink 后以--runtime-image传入。五、资源目录--resource-dir定制打包资源的完整清单手册的 jpackage resource directory 一节是定制打包外观的关键jpackage 会按特定文件名在资源目录中查找替换资源找到即覆盖内置默认值。以下按平台完整列出受支持的文件。Linux 上运行时考虑的目录文件文件名模式含义默认资源launcher-name.png应用启动器图标JavaApp.pnglauncher-name.desktop配合xdg-desktop-menu使用的 desktop 文件仅当启动器注册了文件关联和/或有图标时生效template.desktop构建 Linux DEB/RPM 安装器时package-name-launcher-name.service将启动器注册为后台服务时的 systemd unit 文件默认资源为unit-template.service。构建 Linux RPM 安装器时package-name.specRPM spec 文件默认资源为template.spec仓库中的默认实现见 template.spec。构建 Linux DEB 安装器时文件名含义默认资源control控制文件template.controlcopyright版权文件template.copyrightpreinstall安装前 shell 脚本template.preinstallprerm移除前 shell 脚本template.prermpostinstall安装后 shell 脚本template.postinstallpostrm移除后 shell 脚本template.postrmWindows 上运行时考虑的目录文件文件名模式含义默认资源launcher-name.ico应用启动器图标JavaApp.icolauncher-name.properties应用启动器可执行文件的 Properties 文件WinLauncher.template构建 Windows MSI/EXE 安装器时文件名模式含义默认资源application-name-post-image.wsf构建应用图像后运行的 Windows 脚本文件WSF—main.wxs主 WiX 项目文件main.wxsoverrides.wxiWiX 项目覆盖文件overrides.wxiservice-installer.exe服务安装器可执行文件当有启动器注册为后台服务时生效—launcher-name-service-install.wxi服务安装器 WiX 项目文件同上条件service-install.wxilauncher-name-service-config.wxi服务安装器 WiX 项目文件同上条件service-config.wxiInstallDirNotEmptyDlg.wxs检查安装目录不存在或为空的安装器 UI 对话框InstallDirNotEmptyDlg.wxsShortcutPromptDlg.wxs配置快捷方式的安装器 UI 对话框ShortcutPromptDlg.wxi的默认资源bundle.wxf应用图像组件层级的 WiX 项目文件—ui.wxf安装器 UI 的 WiX 项目文件—os-condition.wxf阻止在旧版 Windows 上安装的条件文件os-condition.wxfwix-conv.xslWiX 源码转换器当使用 WiX v4 或更新版本时用于把 v3 源码转换为 v4 schemawix3-to-wix4-conv.xsl构建 Windows EXE 安装器时文件名模式含义默认资源WinInstaller.properties安装器可执行文件的 Properties 文件WinInstaller.templatepackage-name-post-msi.wsf为 EXE 构建内嵌 MSI 安装器后运行的 WSF 脚本—installer.exeMSI 安装器的可执行包装器msiwrapper.exe其中installer.exe的默认包装器源码即 MsiWrapper.cppWiX 模板默认资源可在 windows/classes/.../resources 目录中查看如 main.wxs、WinLauncher.template、InstallDirNotEmptyDlg.wxs、ShortcutPromptDlg.wxs。macOS 上运行时考虑的目录文件文件名模式含义默认资源launcher-name.icns应用启动器图标JavaApp.icnsInfo.plist应用属性列表文件Info-lite.plist.templateRuntime-Info.plistJava 运行时属性列表文件Runtime-Info.plist.templateapplication-name.entitlements签名 entitlements 属性列表文件sandbox.plist构建 macOS PKG/DMG 安装器时package-name-post-image.sh构建应用图像后运行的 shell 脚本。构建 macOS PKG 安装器时文件名模式含义默认资源uninstaller卸载器 shell 脚本当有启动器注册为后台服务时生效uninstall.command.templatepreinstall安装前 shell 脚本preinstall.templatepostinstall安装后 shell 脚本postinstall.templateservices-preinstall服务包安装前 shell 脚本同上条件services-preinstall.templateservices-postinstall服务包安装后 shell 脚本同上条件services-postinstall.templatepackage-name-background.png背景图像background_pkg.pngpackage-name-background-darkAqua.png深色背景图像background_pkg.pngproduct-def.plist包属性列表文件product-def.plistpackage-name-launcher-name.plist将启动器注册为后台服务时的 launchd 属性列表文件launchd.plist.template构建 macOS DMG 安装器时文件名模式含义默认资源package-name-dmg-setup.scpt安装 AppleScript 脚本DMGsetup.scptpackage-name-license.plist许可证属性列表文件lic_template.plistpackage-name-background.tiff背景图像background_dmg.tiffpackage-name-volume.icns卷图标JavaApp.icns这些默认资源就是 jpackage 内置的模板存放于各平台的模块源码树中如 Linux 的 JavaApp.png。理解文件名模式 默认资源的对应关系后你只需把同名或按命名规则生成的替换文件放入--resource-dir指定的目录即可在不改动任何源码的前提下定制安装包的外观、安装脚本和启动器行为。六、源码结构速查从选项到产物结合仓库中的jdk.jpackage模块可以把 jpackage 的执行链条对应到具体文件入口Main.javajdk.jpackage.main.Main是 jdk.jpackage 模块对外暴露的 main 类负责初始化内部 CLI命令行解析Options.java 定义全部选项及其作用域scope配合 OptionsProcessor、StandardOption、StandardValidator 完成解析与校验——手册中与--module互斥仅在指定--main-jar时可用等约束正是由该层的校验器强制执行的领域模型PackageType.java 定义包类型抽象Application.java 与 BundleSpec.java 承载应用 运行时 包属性的完整规格原生启动器应用图像中的可执行文件由 JvmLauncher.cpp 实现它读取启动器配置CfgFile.cpp并按--arguments/--java-options的替换规则展开$VAR、${VAR}及APPDIR/BINDIR/ROOTDIR令牌后启动 JVM平台差异分别由 LinuxLauncher.c、MacLauncher.cpp 与src/jdk.jpackage/windows/native/applauncher/WinLauncher.cpp实现平台打包工具链Windows 安装器基于 WiX模板见 main.wxsEXE 包装器由 MsiWrapper.cpp 编译Linux 的 DEB/RPM 由 shell 脚本与 template.spec 驱动——这正是第五节资源目录可覆盖的目标文件。七、要点小结--type决定产物形态app-image产出可移植的自包含应用图像exe/msi、rpm/deb、pkg/dmg产出原生安装包且必须在目标平台本机构建--module与--main-jar二选一决定应用以模块化还是 classpath 方式启动也决定 jlink 链接的模块范围可用--add-modules、--jlink-options进一步控制--runtime-image是自带运行时的开关既可以省去 jlink 步骤也是创建运行时安装包的必选参数--arguments/--java-options支持运行时令牌展开APPDIR、BINDIR、ROOTDIR与环境变量是编写自适配启动参数的重要手段\$可转义--resource-dir提供文件级定制面图标、desktop 文件、systemd unit、RPM spec、DEB 控制与脚本、WiX 项目、macOS plist 与签名 entitlements 均可通过特定文件名覆盖默认模板资源在各平台模块源码树如src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/、src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/中可直接查阅排查打包行为时--verbose trace,tools可打印全部执行的命令行及其输出是理解 jpackage 内部调用了哪些平台工具wixl、rpmbuild、dpkg、pkgbuild 等的最快手段。【免费下载链接】jdkJDK main-line development https://openjdk.org/projects/jdk项目地址: https://gitcode.com/GitHub_Trending/jd/jdk创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考