简体   繁体   中英

jlink showing error while comparing hashes

I am currently trying to bundle a javaFx test application via maven and jlink into a runtime image. I am using bellsoft liberica 18.0.1 as a jdk and I am running on a IntelliJ IDE. I have used the IDE to setup the project initially (via the wizzard). If I hit javafx:run, everything fires up correctly, the application is displayed and all is fine.

However, running javafx:jlink produces the following error:

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

This appears odd, as I am unsure which hashes are compared at that point. I have tried executing jlink with --fail-never as well as --lax-checksums and ignoreSigningInformation, but nothing appears to help. I have also tried to check the sha-checksums from within my m2-Repository, but I can't nail it down that way either.

Any help to sort this out is much appreciated.

EDIT: Including the current 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>

EDIT 2: I am providing the jlink-Tool in the pom.xml. My idea was that doing it this way, jlink would be able to create the runtime image based on the liberica-jdk. Is the problem that I am using openjfx-dependencies with the liberica-jlink-Tool?

What the problem is

The module hash mismatch when using jlink occurs because:

  1. You use Liberica "Full JDK" which includes pre-built JavaFX modules in a jmod format AND
  2. You also define JavaFX dependencies in your Maven project based on JavaFX modules in jar format.

This confuses the linker, resulting in the mismatched hash error.

  • The linker knows there are two copies of the same module with the same module version available on the module path, but they have different hashes, so it errors and exits.
  • It would be more useful if the error told you exactly where the two modules with differing hashes were found (you could create an enhancement request with the jlink tool in the JDK for that, referencing this post, if you wanted).

How to fix this

You can fix this by either:

  1. Use a JDK distribution that does not include pre-built JavaFX modules (eg a standard OpenJDK download or a Liberica "Standard JDK" version) OR
  2. Remove the JavaFX dependencies from your pom.xml file.

Getting some link debug info

To debug, in the pom.xml file configuration for the javafx-maven-plugin, add:

<jlinkVerbose>true</jlinkVerbose>

This will tell you where jlink sourced the modules from (when jlink works).

You can also run maven in debug mode ( --debug command line switch for mvn ). Maven will tell you a lot more information. For example, the actual full command line and option set used to invoke jlink.

Here is a debug line for linking using OpenJDK using maven jar dependencies for the JavaFX modules:

[DEBUG] Executing command line: [/Users/myusername/Library/Java/JavaVirtualMachines/openjdk-19.0.1/Contents/Home/bin/jlink, --module-path, /Users/myusername/dev/linktest/target/classes:/Users/myusername/.m2/repository/org/openjfx/javafx-base/19/javafx-base-19-mac.jar:/Users/myusername/.m2/repository/org/openjfx/javafx-controls/19/javafx-controls-19-mac.jar:/Users/myusername/.m2/repository/org/openjfx/javafx-fxml/19/javafx-fxml-19-mac.jar:/Users/myusername/.m2/repository/org/openjfx/javafx-graphics/19/javafx-graphics-19-mac.jar, --add-modules, com.example.linktest, --output, /Users/myusername/dev/linktest/target/app, --strip-debug, --compress, 0, --no-header-files, --no-man-pages, --verbose, --launcher, app=com.example.linktest/com.example.linktest.HelloApplication]

The command line text can be useful because you can copy it and link from the command line prompt rather than from within Maven (just for testing and verification purposes).

Linking using liberica "Full JDK" which includes JavaFX jmods

For your pom.xml with these changes:

  • jlinkExecutable in the javafx-maven-plugin configuration set to the jlink in my liberica location.
    • I don't think this is necessary if the JAVA_HOME environment variable is properly configured to match the liberica distribution and the mvn tool is invoked using the liberica distribution.
  • jlinkVerbose in the javafx-maven-plugin configuration set to true.
  • all JavaFX dependencies commented out.
  • project module and package name changed to com.example.linktest .
    • I just did that because that is what I used to create the project, as long as the name is consistent everywhere, it doesn't matter what it is.

And a minimal module-info.java to generate a basic JavaFX FXML application added. The linker will output:

[INFO] --- javafx-maven-plugin:0.0.8:jlink (default-cli) @ myapp ---
com.example.linktest file:///Users/myusername/dev/linktest/target/classes/
java.base file:///Users/myusername/Library/Java/JavaVirtualMachines/liberica-19.0.1/jmods/java.base.jmod
java.datatransfer file:///Users/myusername/Library/Java/JavaVirtualMachines/liberica-19.0.1/jmods/java.datatransfer.jmod
java.desktop file:///Users/myusername/Library/Java/JavaVirtualMachines/liberica-19.0.1/jmods/java.desktop.jmod
java.prefs file:///Users/myusername/Library/Java/JavaVirtualMachines/liberica-19.0.1/jmods/java.prefs.jmod
java.scripting file:///Users/myusername/Library/Java/JavaVirtualMachines/liberica-19.0.1/jmods/java.scripting.jmod
java.xml file:///Users/myusername/Library/Java/JavaVirtualMachines/liberica-19.0.1/jmods/java.xml.jmod
javafx.base file:///Users/myusername/Library/Java/JavaVirtualMachines/liberica-19.0.1/jmods/javafx.base.jmod
javafx.controls file:///Users/myusername/Library/Java/JavaVirtualMachines/liberica-19.0.1/jmods/javafx.controls.jmod
javafx.fxml file:///Users/myusername/Library/Java/JavaVirtualMachines/liberica-19.0.1/jmods/javafx.fxml.jmod
javafx.graphics file:///Users/myusername/Library/Java/JavaVirtualMachines/liberica-19.0.1/jmods/javafx.graphics.jmod
jdk.unsupported file:///Users/myusername/Library/Java/JavaVirtualMachines/liberica-19.0.1/jmods/jdk.unsupported.jmod

All of the JavaFX dependencies are sourced from the liberica provided jmods, such as this:

liberica-19.0.1/jmods/javafx.base.jmod

Linking using OpenJDK and JavaFX maven jars

If instead you use a standard OpenJDK without pre-built JavaFX modules and JavaFX modules added as dependencies in the pom.xml, then the output is:

[INFO] --- javafx-maven-plugin:0.0.8:jlink (default-cli) @ myapp ---
com.example.linktest file:///Users/myusername/dev/linktest/target/classes/
java.base file:///Users/myusername/Library/Java/JavaVirtualMachines/openjdk-19.0.1/Contents/Home/jmods/java.base.jmod
java.datatransfer file:///Users/myusername/Library/Java/JavaVirtualMachines/openjdk-19.0.1/Contents/Home/jmods/java.datatransfer.jmod
java.desktop file:///Users/myusername/Library/Java/JavaVirtualMachines/openjdk-19.0.1/Contents/Home/jmods/java.desktop.jmod
java.prefs file:///Users/myusername/Library/Java/JavaVirtualMachines/openjdk-19.0.1/Contents/Home/jmods/java.prefs.jmod
java.scripting file:///Users/myusername/Library/Java/JavaVirtualMachines/openjdk-19.0.1/Contents/Home/jmods/java.scripting.jmod
java.xml file:///Users/myusername/Library/Java/JavaVirtualMachines/openjdk-19.0.1/Contents/Home/jmods/java.xml.jmod
javafx.base file:///Users/myusername/.m2/repository/org/openjfx/javafx-base/19/javafx-base-19-mac.jar
javafx.controls file:///Users/myusername/.m2/repository/org/openjfx/javafx-controls/19/javafx-controls-19-mac.jar
javafx.fxml file:///Users/myusername/.m2/repository/org/openjfx/javafx-fxml/19/javafx-fxml-19-mac.jar
javafx.graphics file:///Users/myusername/.m2/repository/org/openjfx/javafx-graphics/19/javafx-graphics-19-mac.jar
jdk.unsupported file:///Users/myusername/Library/Java/JavaVirtualMachines/openjdk-19.0.1/Contents/Home/jmods/jdk.unsupported.jmod

The javafx modules are sourced as jars out of the.m2 repository rather than coming as mods from the JDK:

.m2/repository/org/openjfx/javafx-base/19/javafx-base-19-mac.jar

Either way, you end up with a packaged, linked, usable JavaFX application.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM