Jenesis构建工具入门指南

Jenesis构建工具入门指南

💡 原文英文,约3100词,阅读约需11分钟。
📝

内容提要

作者使用新Java构建工具Jenesis构建Hypersistence Utils项目,该项目包含三个Hibernate模块和近千个集成测试。Jenesis直接读取pom.xml,无需迁移,可与Maven并行使用。需配置jenesis.properties等文件:设置process.concurrency=1以避免共享数据库冲突,补充-g以保留调试信息,并显式传递Docker环境变量。构建产物与Maven一致,额外嵌入SBOM,构建可复现,无改动重跑约需一秒。但增量测试因注解引用识别不足暂不可用,依赖版本仲裁与Maven略有差异。

🔎

延伸解读

并行构建的数据库冲突风险

文章指出,Jenesis 默认并行运行各模块的测试 JVM,而 Hypersistence Utils 的三个模块共用同一套本地数据库,导致一个模块删表时另一个模块仍在用表,出现大量 SQLGrammarException。作者通过设置 jenesis.process.concurrency=1 让工具串行执行,才解决该问题。这提醒读者:若项目测试共享数据库,应在首次全量构建前就限制并发,而不是等失败后再排查。

依赖仲裁差异与版本固定取舍

Jenesis 与 Maven 在“最近优先”策略下对同深度依赖的取舍不同,导致 byte-buddy、jakarta.activation-api 等三个版本不一致。作者尝试用 pin 固定所有依赖并校验 SHA-256,但发现这会向 POM 增加 1,692 行,且 Maven 也会受影响,升级依赖需重新 pin。最终只为三个冲突依赖显式声明版本,既让两者解析一致,又避免冻结全部传递依赖。

增量测试的识别盲区

Jenesis 的增量测试依据类文件常量池、字段类型和方法描述符构建可达图,但注解中的类值以描述符字符串存储,不会被识别为类引用。因此修改 PostgreSQLHStoreType 后,真正测试它的 PostgreSQLHStoreTypeTest 未被选中,只运行了 6 个无关测试。由于该项目超过一半测试文件使用 @Type 注解,作者建议暂时跳过增量测试,等待工具补充对注解值的支持。

调试信息与构建可复现性

Jenesis 默认不向 javac 传递 -g,导致类文件缺少 LocalVariableTable,调试时看不到局部变量名;通过 process-javac.properties 添加 -g 后,类文件大小与 Maven 一致。另一方面,Jenesis 为每个 jar 条目记录固定时间戳 1980-02-01T00:00:00Z,使二次构建可逐步骤比对并确认可复现。这两点说明:迁移构建工具时,编译参数和归档时间戳等细节会直接影响产物与调试体验。

❓

Q&A

Jenesis 构建工具需要什么 Java 版本?

Jenesis 运行在 Java 25 或更新版本上,并且拒绝使用更旧的工具链。

如何在不迁移 pom.xml 的情况下使用 Jenesis 构建现有 Maven 项目?

Jenesis 可以直接读取现有的 pom.xml 文件,因此无需迁移。只需在项目根目录运行 java build/jenesis/Make.java 即可开始构建,并且可以与 Maven 并行使用。

为什么在 Hypersistence Utils 项目中需要设置 jenesis.process.concurrency=1?

因为三个模块的测试共享相同的本地数据库,而 Jenesis 默认并行运行测试 JVM,导致一个模块删除表时另一个模块还在使用,从而引发测试失败。设置该参数可以限制一次只运行一个工具(编译器或测试 JVM),避免冲突。

Jenesis 构建的 jar 与 Maven 构建的 jar 有什么主要区别?

Jenesis 构建的 jar 条目与 Maven 基本一致,但额外嵌入了 CycloneDX SBOM 文件(位于 META-INF/sbom/ 下),并且清单中包含了 Sbom-Format 和 Sbom-Location 属性。此外,类文件可能因编译参数不同而有差异(如缺少 -g 导致调试信息丢失)。

如何让 Jenesis 在编译时保留调试信息(如局部变量表)?

需要创建 build.jenesis/process-javac.properties 文件,并添加 -g= 配置,这样 javac 就会传递 -g 标志,生成包含局部变量表的类文件。

Jenesis 的增量测试功能目前有什么限制?

增量测试功能因无法识别注解中引用的类而暂不可用。例如,测试类通过 @Type(PostgreSQLHStoreType.class) 引用目标类时,Jenesis 无法从常量池中追踪到该依赖,导致相关测试被遗漏。因此,在支持注解值之前,需要跳过该功能。

如何确保 Jenesis 构建的可重复性?

Jenesis 默认将 jar 条目时间戳固定为 1980-02-01T00:00:00Z,因此构建是可重复的。可以使用 -Djenesis.project.reproduce=target-repro 参数进行第二次构建并比较输出,验证可重复性。

Jenesis 的依赖版本仲裁与 Maven 有什么不同?

Jenesis 使用与 Maven 不同的最近优先策略。当依赖路径深度相同时,Maven 选择先声明的依赖,而 Jenesis 选择后声明的依赖。例如,byte-buddy 在 hibernate-core 和 mockito-core 中版本冲突时,Maven 选 hibernate-core 的版本,Jenesis 选 mockito-core 的版本。可以通过在 dependencyManagement 中显式指定版本来统一解析结果。

🏷️

标签

➡️

继续阅读