jar_pack

一个基于 Golang embed 打包自定义的 JRE 和 JAR 文件的跨平台打包工具,方便打包 JAR 程序进行二进制分发。

系统架构

graph TD;
    A[jar_pack 工具] --> B[准备 JRE]
    A --> C[准备 JAR]
    A --> D[编译]
    B --> E[JRE 目录]
    C --> F[JAR 文件]
    D --> G[输出二进制文件]
    E --> H[嵌入 JRE]
    F --> H[嵌入 JAR]
    G --> H[生成可执行文件]

使用示例(Java 8 版本环境打包到 Linux x86 下运行)

步骤 1: 准备指定版本以及系统的 JRE

从 Azul 下载并解压到 /jre 目录下。

步骤 2: 准备需要打包的 JAR

将 JAR 重命名为 app.jar

mv your-app.jar app.jar

步骤 3: 打包 Java 程序依赖的本地库

将本地库文件解压到 /lib 目录下。(可选)

mv xxx.dll lib/
mv xxx.so lib/

步骤 4: 编译

GOOS=linux GOARCH=amd64 go build -o app

运行

运行 ./app 或者指定 JVM 参数运行 ./app --spring.config.location=./application.yml

Windows 系统特殊说明

使用 rsrc 工具嵌入图标

  • 查找并保存 favicon.ico 图标到程序同级目录。
  • 新建程序描述文件 app.manifest,写入以下内容:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    <assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="SomeFunkyNameHere" type="win32"/>
    <dependency>
        <dependentAssembly>
            <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
        </dependentAssembly>
    </dependency>
    <asmv3:application>
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
            <dpiAware>true</dpiAware>
        </asmv3:windowsSettings>
    </asmv3:application>
</assembly>
  • 生成资源嵌入文件 rsrc.syso
rsrc -manifest app.manifest -o rsrc.syso -ico favicon.ico
  • 编译时隐藏黑窗口:
go build -ldflags "-s -w -H=windowsgui"
  • 双击 exe 文件即可运行。

剪裁 JRE

Java 9 引入的一项功能,用于创建自定义的 JRE。这个自定义 JRE 只包含应用程序运行所需的模块,从而减少了体积。

分析依赖

使用 jdeps 工具分析 JAR 文件,确定需要的模块。假设你的应用程序 JAR 文件名为 app.jar

jdeps --list-deps app.jar

创建自定义 JRE

根据 jdeps 的输出,使用 jlink 创建自定义 JRE。例如,假设你的应用程序需要以下模块:

jlink --module-path $JAVA_HOME/jmods --add-modules java.base,java.logging --output custom-jre

运行原理

$JAVAW||$JAVA -Djava.library.path=$LIB -jar $JAR $ARGS...

工作流程

sequenceDiagram
    participant U as 用户
    participant J as jar_pack
    participant F as 文件系统
    U->>J: 准备 JRE
    J->>F: 解压 JRE 到 /jre 目录
    U->>J: 准备 JAR 文件
    J->>F: 移动 JAR 文件到 /app.jar
    U->>J: 准备本地库
    J->>F: 移动本地库到 /lib 目录
    U->>J: 编译项目
    J->>F: 生成可执行文件 app
    U->>J: 运行 app
    J->>J: 嵌入 JRE 和 JAR
    J->>F: 输出可执行文件