使用Maven+jlink打包JavaFX应用时哈希对比报错求助
问题背景
使用BellSoft Liberica 18.0.1作为JDK,通过IntelliJ向导初始化Maven项目,执行javafx:run可正常启动JavaFX应用,但运行javafx:jlink时出现哈希校验错误:
Error: Hash of javafx.base
(d775513043c11c457939b41e544cc7a83a4076454da4a0798bdc6922ec7d3f8f)
differs to expected hash
(eb1d4f72b292e9bf33005b36c4afeda11b66a8745b868bf0593d1cd4c2974681)
recorded in java.base java.lang.module.FindException: Hash of
javafx.base
(d775513043c11c457939b41e544cc7a83a4076454da4a0798bdc6922ec7d3f8f)
differs to expected hash
(eb1d4f72b292e9bf33005b36c4afeda11b66a8745b868bf0593d1cd4c2974681)
recorded in java.base
已尝试添加--fail-never、--lax-checksums、ignoreSigningInformation参数无效,怀疑是OpenJFX依赖搭配Liberica jlink工具导致冲突。
当前pom.xml内容:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.test</groupId> <artifactId>myapp</artifactId> <version>1.0-SNAPSHOT</version> <name>myappMavenModulebased</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <junit.version>5.9.1</junit.version> </properties> <dependencies> <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-base --> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-base</artifactId> <version>19</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-controls</artifactId> <version>19</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-fxml</artifactId> <version>19</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-web</artifactId> <version>19</version> </dependency> <dependency> <groupId>org.controlsfx</groupId> <artifactId>controlsfx</artifactId> <version>11.1.2</version> </dependency> <dependency> <groupId>com.dlsc.formsfx</groupId> <artifactId>formsfx-core</artifactId> <version>11.5.0</version> <exclusions> <exclusion> <groupId>org.openjfx</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>net.synedra</groupId> <artifactId>validatorfx</artifactId> <version>0.3.1</version> <exclusions> <exclusion> <groupId>org.openjfx</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.kordamp.ikonli</groupId> <artifactId>ikonli-javafx</artifactId> <version>12.3.1</version> </dependency> <dependency> <groupId>org.kordamp.bootstrapfx</groupId> <artifactId>bootstrapfx-core</artifactId> <version>0.4.0</version> </dependency> <dependency> <groupId>eu.hansolo</groupId> <artifactId>medusa</artifactId> <version>16.0.1</version> <exclusions> <exclusion> <groupId>org.openjfx</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <!-- Build an executable JAR --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.1.0</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>com.test.myapp.AppLauncher</mainClass> </manifest> </archive> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.10.1</version> <configuration> <source>18</source> <target>18</target> </configuration> </plugin> <plugin> <groupId>org.openjfx</groupId> <artifactId>javafx-maven-plugin</artifactId> <version>0.0.8</version> <executions> <execution> <!-- Default configuration for running with: mvn clean javafx:run --> <id>default-cli</id> <configuration> <mainClass>com.test.myapp/com.test.myapp.HelloApplication</mainClass> <launcher>app</launcher> <jlinkZipName>app</jlinkZipName> <jlinkImageName>app</jlinkImageName> <noManPages>true</noManPages> <stripDebug>true</stripDebug> <noHeaderFiles>true</noHeaderFiles> <failNever>true</failNever> <ignoreSigningInformation>true</ignoreSigningInformation> <jlinkExecutable>/home/user/.jdks/bellsoft-jdk19.0.1/bin/jlink</jlinkExecutable> </configuration> </execution> </executions> </plugin> </plugins> </build>
解决方案
核心问题分析
- 版本不匹配:Liberica JDK 18.0.1自带JavaFX 18,但pom.xml里依赖的是OpenJFX 19,版本差异导致哈希校验不通过。
- 签名冲突:Liberica的JavaFX模块是官方签名的,和OpenJFX的签名哈希值不同,jlink在合并模块时会校验签名一致性,从而报错。
- JDK工具版本混乱:pom里指定的jlink是Liberica 19.0.1的工具,而项目编译用的是JDK 18,版本不一致加剧问题。
具体修复步骤
方案一:统一版本,使用Liberica自带JavaFX
- 移除OpenJFX依赖:Liberica JDK自带JavaFX模块,不需要再引入
org.openjfx的依赖,直接删除pom.xml中所有javafx-base、controls、fxml、web的依赖项。 - 修正jlink路径:将
jlinkExecutable路径改为Liberica 18.0.1的jlink工具路径,比如/home/user/.jdks/bellsoft-jdk18.0.1/bin/jlink,确保和编译用的JDK版本一致。 - 验证配置:确保maven-compiler-plugin的source/target保持18,和JDK版本匹配。
方案二:改用OpenJFX 18,匹配Liberica JDK版本
- 降级OpenJFX版本:将pom.xml中所有OpenJFX依赖的version从19改为18,和Liberica 18.0.1的JavaFX版本对齐。
- 修正jlink路径:同样要确保jlinkExecutable指向Liberica 18.0.1的工具,避免版本混乱。
- 保留ignoreSigningInformation参数:由于Liberica JDK的java.base可能和OpenJFX的签名有差异,保留
ignoreSigningInformation>true</ignoreSigningInformation配置。
修正后的pom.xml示例(方案一)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.test</groupId> <artifactId>myapp</artifactId> <version>1.0-SNAPSHOT</version> <name>myappMavenModulebased</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <junit.version>5.9.1</junit.version> </properties> <dependencies> <dependency> <groupId>org.controlsfx</groupId> <artifactId>controlsfx</artifactId> <version>11.1.2</version> </dependency> <dependency> <groupId>com.dlsc.formsfx</groupId> <artifactId>formsfx-core</artifactId> <version>11.5.0</version> <exclusions> <exclusion> <groupId>org.openjfx</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>net.synedra</groupId> <artifactId>validatorfx</artifactId> <version>0.3.1</version> <exclusions> <exclusion> <groupId>org.openjfx</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.kordamp.ikonli</groupId> <artifactId>ikonli-javafx</artifactId> <version>12.3.1</version> </dependency> <dependency> <groupId>org.kordamp.bootstrapfx</groupId> <artifactId>bootstrapfx-core</artifactId> <version>0.4.0</version> </dependency> <dependency> <groupId>eu.hansolo</groupId> <artifactId>medusa</artifactId> <version>16.0.1</version> <exclusions> <exclusion> <groupId>org.openjfx</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <!-- Build an executable JAR --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.1.0</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>com.test.myapp.AppLauncher</mainClass> </manifest> </archive> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.10.1</version> <configuration> <source>18</source> <target>18</target> </configuration> </plugin> <plugin> <groupId>org.openjfx</groupId> <artifactId>javafx-maven-plugin</artifactId> <version>0.0.8</version> <executions> <execution> <!-- Default configuration for running with: mvn clean javafx:run --> <id>default-cli</id> <configuration> <mainClass>com.test.myapp/com.test.myapp.HelloApplication</mainClass> <launcher>app</launcher> <jlinkZipName>app</jlinkZipName> <jlinkImageName>app</jlinkImageName> <noManPages>true</noManPages> <stripDebug>true</stripDebug> <noHeaderFiles>true</noHeaderFiles> <failNever>true</failNever> <ignoreSigningInformation>true</ignoreSigningInformation> <jlinkExecutable>/home/user/.jdks/bellsoft-jdk18.0.1/bin/jlink</jlinkExecutable> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
内容的提问来源于stack exchange,提问作者Christian

