PR7950 Java 打包启动流程说明
PR7950 Java 打包、压缩、XJar 加密与启动流程说明
整个流程从 build.sh 开始,先构建 Java 模块,再按清单提取业务 fat jar,随后用压缩工具拆分公共依赖,再使用 XJar 加密,最后把产物同步到 binary/java 运行目录。启动时不是直接执行 java -jar,而是通过 xjar java ... -jar 服务.jar 解密运行。
1. 总体流程
整个流程从 build.sh 开始,先构建 Java 模块,再按清单提取业务 fat jar,随后用压缩工具拆分公共依赖,再使用 XJar 加密,最后把产物同步到 binary/java 运行目录。启动时不是直接执行 java -jar,而是通过 xjar java ... -jar 服务.jar 解密运行。
流程步骤
- build.sh: 准备 JDK/Maven,同步 encrypt XML
- Maven Build: 构建 platform 与 platapp
- x64_raw: 按 jar_list.txt 提取原始 fat jar
- compress: 拆分 BOOT-INF/lib 依赖
- lib/common: 输出公共 jar 与 requirements.txt
- XJar: 加密压缩后的服务 jar
- binary: 同步 jar 与公共依赖到运行目录
- startup: xjar java 启动,动态加载公共依赖
一句话概括:
打包阶段把业务 jar 变小并加密,启动阶段用 XJar 解密运行,再由sunri-spring-classload把拆出去的公共依赖加载回来。
2. 构建与提取 Jar
入口脚本位于:/home/liumangmang/IdeaProjects/PR7950/V1.00_2024/src_java/package/build.sh
执行入口
cd /home/liumangmang/IdeaProjects/PR7950/V1.00_2024/src_java/package
bash build.sh环境准备
脚本根据机器架构选择内置 JDK,并使用项目自带 Maven。
| 项目 | 路径/规则 |
|---|---|
| x86_64 JDK | src_java/package/jdk-x64 |
| ARM JDK | src_java/package/jdk-arm |
| Maven | src_java/package/maven |
| 原始 jar 目标目录 | src_java/package/java/jar/x64_raw |
Maven 构建顺序
cd src_java/platform
mvn clean install -DskipTests -T 1C
cd src_java/platapp
mvn clean package -DskipTests -T 1C按 jar_list.txt 提取业务 Jar
build.sh 读取 src_java/package/jar_list.txt,在 platform 和 platapp 的 target 目录中查找同名 jar,排除 original-*,复制到 x64_raw。
src_java/package/jar_list.txt
src_java/platform/**/target/*.jar
src_java/platapp/**/target/*.jar
↓
src_java/package/java/jar/x64_raw/*.jar3. 压缩与依赖拆分
压缩工具源码位于:/home/liumangmang/IdeaProjects/PR7950/V1.00_2024/src_java/tool/sunri-package-compress-xjar/
构建产物是带依赖的可执行 jar:target/sunri-package-compress-xjar-1.0-jar-with-dependencies.jar
配置文件
脚本从模板生成实际配置:src_java/package/java/tools/model_compress-xjar.config -> src_java/package/java/tools/compress-xjar.config
| 配置项 | 作用 |
|---|---|
entryptXmlDir | 读取每个服务的加密/保留依赖 XML,实际来自 src_java/package/java/bin/encrypt/ |
rawJarDir | 原始 fat jar 输入目录:src_java/package/java/jar/x64_raw |
compressJarDir | 压缩后 jar 输出目录:src_java/package/java/jar/x64_compress |
libDir | 被拆出去的公共依赖输出目录:src_java/package/java/lib/common |
xjarDir | XJar 加密后 jar 输出目录:src_java/package/java/jar/x64 |
enableCompress | 1 启用压缩,0 不压缩 |
依赖拆分规则
压缩逻辑在 JarUtil.compress 中实现,扫描 Spring Boot fat jar 的 BOOT-INF/lib/*.jar。符合以下条件的依赖会保留在业务 jar 内,其余依赖会被提取到 lib/common。
cygbusiness-*开头的 jar 保留。sunri-*开头的 jar 保留。- 当前服务 XML 的
<include>中声明的 jar 保留。 - 其他 jar 从业务 jar 删除,并复制到
lib/common。
每个服务还会生成一个依赖清单:src_java/package/java/lib/common/服务名-requirements.txt
该清单记录当前服务启动时需要从公共目录加载哪些被拆出去的 jar。
4. XJar 加密
压缩后,工具使用 XJar 对服务 jar 加密。相关代码位于:src_java/tool/sunri-package-compress-xjar/src/main/java/com/sunri/Main.java
使用的依赖是:
<dependency>
<groupId>com.github.core-lib</groupId>
<artifactId>xjar</artifactId>
<version>4.0.1</version>
</dependency>默认加密参数
| 项目 | 值 |
|---|---|
| 密码 | xtptweb |
| include | /com/sunri/**, *.yaml, mapper/**.xml, *.yml |
| exclude | 空 |
工具先输出 服务名.xjar,成功后再重命名为 服务名.jar。因此发布目录中看到的是 .jar 文件,但内容已经经过 XJar 处理。
x64_compress/服务名.jar
↓ XJar encryption
x64/服务名.xjar
↓ rename
x64/服务名.jar注意:
src_java/platform/01_componnet/08_sunri-package-xjar/是历史/图形化加密工具组件;当前build.sh实际调用的是src_java/tool/sunri-package-compress-xjar/。
5. 同步到 binary 运行目录
加密后的服务 jar 从源码打包目录复制到运行目录:
src_java/package/java/jar/x64/*.jar
↓
binary/java/jar/x64/*.jar公共依赖和 *-requirements.txt 从源码打包目录复制到运行目录:
src_java/package/java/lib/common/
↓
binary/java/lib/common/最终运行目录关键结构如下:
binary/java/bin/
binary/java/bin/encrypt/
binary/java/jar/x64/
binary/java/jar/x64/xjar
binary/java/lib/common/关键前提:
binary/java/jar/x64/xjar是 Linux x86_64 可执行文件,启动加密 jar 时必须存在并具备执行权限。当前build.sh不负责编译这个可执行文件,只依赖运行目录已预置。
6. 启动流程
业务启动脚本位于:/home/liumangmang/IdeaProjects/PR7950/V1.00_2024/binary/java/bin/
启动前需要设置 PRJHOME 指向项目运行根目录:
export PRJHOME=/home/liumangmang/IdeaProjects/PR7950/V1.00_2024启动、停止、重启示例
bash ${PRJHOME}/binary/java/bin/cygsystemweb.sh start
bash ${PRJHOME}/binary/java/bin/cygsystemweb.sh stop
bash ${PRJHOME}/binary/java/bin/cygsystemweb.sh restart每个业务脚本都会设置服务名、jar 路径、公共依赖路径和 JVM 参数,然后调用统一控制脚本:
JAVA_PROC_ROOT=${PRJHOME}/binary/java
JAVA_PROC_NAME="cygsystemweb"
JAVA_PROC_JAR_PATH=${JAVA_PROC_ROOT}/jar/x64/${JAVA_PROC_NAME}.jar
JAVA_PROC_LIB_PATH=${JAVA_PROC_ROOT}/lib/common
JVM_OPTS="-Xms512M -Xmx512M"
/bin/bash ${JAVA_PROC_ROOT}/bin/javacontrol.sh \
${JAVA_PROC_JAR_PATH} start ${JAVA_PROC_LIB_PATH} "${JVM_OPTS}"javacontrol.sh 最终命令
真正启动时不是直接 java -jar,而是通过 xjar 包装 java 命令:
nohup ${PRJHOME}/binary/java/jar/x64/xjar java \
-Dplainload.dir.path=${PRJHOME}/binary/java/lib/common \
-Djava.io.tmpdir=/home/sunri/patrolTemp \
-Dplainload.include.file=cygsystemweb-requirements.txt \
-DenableSkipAuth=false \
-Djava.net.preferIPv4Stack=true \
-Dfile.encoding=utf-8 \
-Duser.timezone=Asia/Shanghai \
-Drds.dynamic.sql=true \
-Xms512M -Xmx512M \
-XX:+UseG1GC \
-XX:ParallelGCThreads=8 \
-XX:NativeMemoryTracking=summary \
-jar ${PRJHOME}/binary/java/jar/x64/cygsystemweb.jar \
> /dev/null 2>&1 &7. 动态加载公共依赖
公共依赖动态加载组件位于:/home/liumangmang/IdeaProjects/PR7950/V1.00_2024/src_java/platform/01_componnet/06_sunri-spring-classload/
该组件通过 META-INF/spring.factories 注册 Spring Boot 早期监听器:
org.springframework.context.ApplicationListener=\
com.sunri.PlainTextClassLoaderPlainTextClassLoader 启动时读取两个 JVM 参数:
| 参数 | 作用 |
|---|---|
-Dplainload.dir.path | 公共依赖目录,例如 binary/java/lib/common |
-Dplainload.include.file | 当前服务的依赖清单,例如 cygsystemweb-requirements.txt |
加载过程是:读取 binary/java/lib/common/服务名-requirements.txt,再把清单中的 jar 通过反射调用 URLClassLoader.addURL 加入当前 classloader。
binary/java/lib/common/
├── cygsystemweb-requirements.txt
├── jackson-databind-*.jar
├── mysql-connector-*.jar
└── ...
PlainTextClassLoader
↓ read requirements
↓ addURL(jar)
Spring Boot application continues startup运行时 classpath 组成:
加密服务 jar 内保留的依赖,加上lib/common中按requirements.txt动态加载的依赖。
8. 新增服务维护清单
如果后续新增一个 Java 服务,需要同时维护以下内容,保证打包和启动链路完整。
- 在
src_java/package/jar_list.txt增加新服务.jar。 - 确认 Maven 构建后能在
platform或platapp的target下生成同名 jar。 - 在
binary/java/bin/encrypt/增加新服务.xml,并确保根节点service="新服务"。 - 在 XML 中声明压缩后必须保留在业务 jar 内的依赖,尤其是 Spring Boot 核心依赖、启动早期依赖、业务 SPI 和不能拆出的内部包。
- 在
binary/java/bin/增加新服务.sh,设置JAVA_PROC_NAME、JVM_OPTS等参数。 - 执行
build.sh后确认生成binary/java/jar/x64/新服务.jar。 - 确认生成
binary/java/lib/common/新服务-requirements.txt。 - 启动前确认
PRJHOME、xjar执行权限、公共依赖目录都正确。
9. 快速参考
打包命令
cd /home/liumangmang/IdeaProjects/PR7950/V1.00_2024/src_java/package
bash build.sh启动命令
export PRJHOME=/home/liumangmang/IdeaProjects/PR7950/V1.00_2024
bash ${PRJHOME}/binary/java/bin/cygsystemweb.sh start加密后 Jar
binary/java/jar/x64/*.jar公共依赖
binary/java/lib/common/
binary/java/lib/common/*-requirements.txt本文档根据当前仓库脚本和源码整理,重点覆盖 build.sh、sunri-package-compress-xjar、sunri-spring-classload、XJar 运行入口与 binary/java/bin 启动脚本。
