java - jdeps 在 fat jar 中使用 Java 11 和 JavaFX 失败

标签 java javafx jlink javafx-11 jdeps

我正在尝试使用 jdeps(和 jlink)来部署使用 JavaFX 11 的 Java 11 应用程序。在我的 Java IDE 中运行一切正常。但是当我使用 jdep 时出现以下错误,这表明找不到某些模块或包。我卡住了。感谢您的帮助。

jdeps --list-deps --module-path /Users/…/target:/Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home/jmods:/Users/…/javafx-sdk-11.0.2/lib --add-modules chaincoder,javafx.fxml,javafx.base,javafx.controls,javafx.graphics,javafx.web /Users/…/target/chaincoder4-1.0.jar

Error: Module javafx.media contains package javafx.collections, module javafx.base exports package javafx.collections to javafx.media

module-info.java 是

模块链编码器{

requires   javafx.web;
requires   javafx.graphics;
requires   javafx.controls;
requires   javafx.fxml;
requires   javafx.base;
requires   javafx.media;

requires java.desktop;
requires java.base;
requires java.xml;
requires java.logging;

requires jdk.jsobject;

exports   core;

pom.xml 是

        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-graphics</artifactId>
            <version>11.0.2</version>
        </dependency>

        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>11.0.2</version>
        </dependency>

        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-base</artifactId>
            <version>11.0.2</version>
        </dependency>

        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-media</artifactId>
            <version>11.0.2</version>
        </dependency>

        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-web</artifactId>
            <version>11.0.2</version>
        </dependency>

        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>11.0.2</version>
        </dependency>


<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>core.Main</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.6</version>
            <executions>
                <execution>
                    <id>unpack-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>unpack-dependencies</goal>
                    </goals>
                    <configuration>
                        <excludeScope>system</excludeScope>
                        <excludeGroupIds>junit,org.mockito,org.hamcrest</excludeGroupIds>
                        <outputDirectory>${project.build.directory}/classes</outputDirectory>
                    </configuration>
                </execution>
            </executions>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.0</version>
            <configuration>
                <source>11</source>
                <target>11</target>
                <compilerArguments>
                    <bootclasspath>${sun.boot.class.path}${path.separator}${java.home}/lib/jfxrt.jar</bootclasspath>
                </compilerArguments>
            </configuration>
        </plugin> 
    </plugins>

</build>

最佳答案

您使用 maven-dependency-plugin 插件的原因是什么?

如果您看到 unpack-dependencies 目标在做什么,您会注意到 target/classes 文件夹包含超过 90 MB 的类,在插件提取后所有项目依赖项,包括 JavaFX 依赖项,并将它们全部组合起来。

猜猜每个不同的 JavaFX 模块的不同 module-info.class 文件会发生什么情况?只有一个占上风,在本例中是来自 javafx.media 的那个。

所以你已经在 target/classes 中创建了一个新模块!

它名为 javafx.media,包含您的项目类和所有 JavaFX 类,并且包括所有来自 javafx.basejavafx.graphics.

如果您检查此 target/classes/module-info.class 文件:

module javafx.media {
    requires transitive javafx.base;
    requires transitive javafx.graphics;
    ...
}

这个已经包含所有 JavaFX 类的“模块”还需要 再次 javafx.basejavafx.graphics,复制它们。

这解释了您的错误消息:

Error: Module javafx.media contains package javafx.collections, 
       module javafx.base exports package javafx.collections to javafx.media

现在您可以看到您的模块 javafx.media 包含许多包,这些包也从 javafx.base 导出到它,并且违反了 split package not allowed条件:

The same Java package can only be exported by a single Java module at runtime. In other words, you cannot have two (or more) modules that export the same package in use at the same time. The Java VM will complain at startup if you do.

可能的解决方案

  • 也许您根本不需要maven-dependency-plugin 插件?如果不需要,请将其删除。

  • 您正在将包含所有 JavaFX 类的 target 文件夹添加到模块路径:

    jdeps --list-deps --module-path /Users/…/target:...
    

显然这是错误的,因为 classes 文件夹包含所有 JavaFX 类和一个错误的模块信息描述符。它不是有效模块,因此只需将其从模块路径中删除。

  • 那么您不需要将 JDK 路径添加到模块路径,这是默认完成的。

所以你可以:

jdeps --list-deps --module-path /Users/…/javafx-sdk-11.0.2/lib
  • 然后,当您添加模块时,您不需要添加 javafx.basejavafx.graphics,因为它们包含在传递依赖项中(这也是适用于您的 pom 中列出的依赖项)。参见例如 javafx.web .

所以你将拥有:

jdeps --list-deps --module-path /Users/…/javafx-sdk-11.0.2/lib
    -add-modules chaincoder,javafx.fxml,javafx.web
  • 但请注意,您有一个名为 chaincoder 的模块,它已经包含了所有需要的模块,因此您可以只拥有这个:

    jdeps --list-deps --module-path /Users/…/javafx-sdk-11.0.2/lib
        -add-modules chaincoder /Users/…/target/chaincoder4-1.0.jar
    

这应该有效。

最后一点,您可以从编译器插件中删除 jfxrt.jar:

<configuration>
    <source>11</source>
    <target>11</target>
    <compilerArguments>
            <bootclasspath>${sun.boot.class.path}${path.separator}${java.home}/lib/jfxrt.jar</bootclasspath>
    </compilerArguments>
</configuration>

因为它已经不存在了。您已将所有 JavaFX 类包含在依赖项中:

<configuration>
    <source>11</source>
    <target>11</target>
</configuration>

关于java - jdeps 在 fat jar 中使用 Java 11 和 JavaFX 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54741351/

相关文章:

java - 是否可以将 List<Key> 作为实体的属性存储在 Google App Engine (GAE) 中?

java - 致力于在 JavaFX 中创建图片库。无法正常显示图像

java - JLink 不生成可重新分发的图像

java - jlink:应用程序 jar 未在/bin 文件夹中创建

java - 在 Pro-Engineer 中调试 JLink 应用程序

java - 如何在java中添加自己的数字范围

java - 无法读取 servlet 中的表单域

java - 运行所有测试但覆盖范围未显示

css - 带有图像的 JavaFX CSS 按钮 - 如何定义图像的大小?

java - 调整大小时控件需要保持居中(响应式 UI、JavaFX)