缺少 Maven Shade JavaFX 运行时组件 [英] Maven Shade JavaFX runtime components are missing

查看:37
本文介绍了缺少 Maven Shade JavaFX 运行时组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 maven 依赖项创建 JFX11 自包含 jar.根据我所做的研究,似乎最好的方法是通过 maven shade 插件.但是,当我运行它时,出现此错误:

I'm trying to create a JFX11 self-containing jar using maven dependencies. From the research I've done, it seems the best way to do this is through the maven shade plugin. However, When I run it, I get the this error:

错误:缺少 JavaFX 运行时组件,需要运行此应用程序

Error: JavaFX runtime components are missing, and are required to run this application

我不明白为什么会这样.我在捣乱什么?有一个更好的方法吗?我也尝试过带有相同消息的 Maven 程序集插件.

I don't understand why this is happening. What am I messing up? Is there a better way to do this? I've also tried the maven assembly plugin with the same message.

pom 文件供参考

<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 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>Application</groupId>
    <artifactId>Main</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>SpaceRunner</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>11</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <release>10</release>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.6.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>Application.Main</mainClass>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>
                                Application.Main
                            </mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>Application.Main</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

推荐答案

UPDATE 10/2021

自 JavaFX 16 起,当 JavaFX 不在模块路径上运行时会显示警告,这是 uber/fat jar 的情况:

Since JavaFX 16 a warning is displayed when JavaFX doesn't run on the module path, which is the case of an uber/fat jar:

$ java -jar myFatJar-1.0-SNAPSHOT.jar
Oct 02, 2021 1:45:21 PM com.sun.javafx.application.PlatformImpl startup
WARNING: Unsupported JavaFX configuration: classes were loaded from 'unnamed module @14c24f4c'

此外,您会收到来自 shade 插件本身的警告:

Also, you get a warning from the shade plugin itself:

[WARNING] Discovered module-info.class. Shading will break its strong encapsulation.

虽然这些警告最初可以被忽略,但它们是有原因的.

While these warnings can be initially ignored, there is a reason for them.

如本CSR中所述:

JavaFX 是作为一组命名模块构建和分发的,每个模块都在自己的模块化 jar 文件中,JavaFX 运行时期望从一组命名的 javafx.* 模块加载它的类,并且不支持加载这些模块来自类路径.

JavaFX is built and distributed as a set of named modules, each in its own modular jar file, and the JavaFX runtime expects its classes to be loaded from a set of named javafx.* modules, and does not support loading those modules from the classpath.

还有:

当从类路径加载 JavaFX 类时,它破坏了封装,因为我们不再从 Java 模块系统中受益.

when the JavaFX classes are loaded from the classpath, it breaks encapsulation, since we no longer get the benefit of the java module system.

因此,即使这个被广泛接受的答案也解释了如何在 Maven 项目上创建 uber/fat jar,不鼓励使用它,以及其他现代替代方案来分发您的应用程序,如 jlinkjpackagenative-image,应该使用.

Therefore, even this widely accepted answer explains how can an uber/fat jar can be created on Maven projects, its use is discouraged, and other modern alternatives to distribute your application, like jlink, jpackage or native-image, should be used.

原答案

答案解释了胖/超级 jar 在 JavaFX 11 上失败的原因.简而言之:

This answer explains why a fat/uber jar fails on JavaFX 11. In short:

此错误来自 java.base 模块中的 sun.launcher.LauncherHelper.这样做的原因是 Main 应用程序扩展了 Application 并有一个 main 方法.如果是这种情况,LauncherHelper 将检查 javafx.graphics 模块是否作为命名模块存在.如果该模块不存在,则启动将中止.

This error comes from sun.launcher.LauncherHelper in the java.base module. The reason for this is that the Main app extends Application and has a main method. If that is the case, the LauncherHelper will check for the javafx.graphics module to be present as a named module. If that module is not present, the launch is aborted.

并且已经为 Gradle 提出了修复方案.

And already proposes a fix for Gradle.

对于 Maven,解决方案完全相同:提供一个不从 Application 扩展的新主类.

For Maven the solution is exactly the same: provide a new main class that doesn't extend from Application.

您的 application 包中将有新类(坏名):

You will have new class in your application package (bad name):

// NewMain.java
public class NewMain {

    public static void main(String[] args) {
        Main.main(args);
    }
}

和您现有的 Main 类,原样:

And your existing Main class, as is:

//Main.java
public class Main extends Application {

    @Override
    public void start(Stage stage) {
        ...
    }

    public static void main(String[] args) {
        launch(args);
    }
}

现在你需要修改你的 pom 并为不同的插件设置你的主类:

Now you need to modify your pom and set your main class for the different plugins:

<mainClass>application.NewMain</mainClass>

特定于平台的 Fat jar

最后,使用 shade 插件,您将在您的机器上制作一个胖罐.

Finally, with the shade plugin you are going to produce a fat jar, on your machine.

这意味着,到目前为止,您的 JavaFX 依赖项使用的是唯一的分类器.例如,如果您使用的是 Windows,Maven 将在内部使用 win 分类器.这具有仅包含适用于 Windows 的本机库的效果.

This means that, so far, your JavaFX dependencies are using a unique classifier. If for instance you are on Windows, Maven will be using internally the win classifier. This has the effect of including only the native libraries for Windows.

所以你正在使用:

  • org.openjfx:javafx-controls:11
  • org.openjfx:javafx-controls:11:win
  • org.openjfx:javafx-graphics:11
  • org.openjfx:javafx-graphics:11:win <-- 这包含 Windows 的本机 dll
  • org.openjfx:javafx-base:11
  • org.openjfx:javafx-base:11:win

现在,如果您生成胖 jar,您将捆绑所有这些依赖项(以及您项目中的其他常规第三方依赖项),并且您将能够以以下方式运行您的项目:

Now, if you produce the fat jar, you will bundle all those dependencies (and those other regular third party dependencies from your project), and you will be able to run your project as:

java -jar myFatJar-1.0-SNAPSHOT.jar

虽然这很好,但如果你想分发你的 jar,请注意这个 jar 不是跨平台的,它只能在你的平台上工作,在这种情况下是 Windows.

While this is very nice, if you want to distribute you jar, be aware that this jar is not cross-platform, and it will work only on your platform, in this case Windows.

跨平台胖罐

有一个解决方案可以生成一个可以分发的跨平台 jar:包括其他平台的其余本机库.

There is a solution to generate a cross-platform jar that you can distribute: include the rest of the native libraries of the other platforms.

这很容易做到,因为您只需要包含三个平台的图形模块依赖项:

This can be easily done, as you just need to include the graphics module dependencies for the three platforms:

<dependencies>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-controls</artifactId>
        <version>11</version>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-graphics </artifactId>
        <version>11</version>
        <classifier>win</classifier>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-graphics </artifactId>
        <version>11</version>
        <classifier>linux</classifier>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-graphics </artifactId>
        <version>11</version>
        <classifier>mac</classifier>
    </dependency>
</dependencies>

尺寸

这种方法有一个主要问题:大小.正如您在其他答案中所见,如果您使用 WebView 控件,由于WebKit 原生库.

There is a main issue with this approach: the size. As you can see in this other answer, if you use the WebView control, you will be bundling around 220 MB due to the WebKit native libraries.

这篇关于缺少 Maven Shade JavaFX 运行时组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆