jdeps在胖子罐中因Java 11和JavaFX而失败

时间:2019-02-18 06:11:27

标签: java javafx jlink javafx-11 jdeps

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

  

jdeps --list-deps-模块路径   /用户/…/目标:/库/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home/jmods:/用户/.../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>

1 个答案:

答案 0 :(得分:1)

您为什么使用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

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

  

同一Java包只能在运行时由单个Java模块导出。换句话说,您不能有两个(或更多)模块同时导出使用中的同一软件包。如果您这样做,Java VM将在启动时抱怨。

可能的解决方案

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

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

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

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

  • 然后,您无需将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>