【问题标题】:How to bundle the JavaFX SDK directly in the output jar?如何将 JavaFX SDK 直接捆绑到输出 jar 中?
【发布时间】:2020-05-15 09:00:46
【问题描述】:

目前我在启动我的程序时使用 JVM 参数来查找 JavaFX 库,如下所示:

java -javaagent:lib/aspectjweaver-1.9.5.jar -javaagent:lib/spring-instrument-5.2.3.RELEASE.jar --module-path lib/javafx-sdk-13.0.2/lib --add-modules=javafx.controls -jar target/Some_Service-1.0.jar

我的 POM.xml 的插件部分非常简单。除了 Docker 和 Launch4j 插件,我只有这个:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>

有没有办法告诉 Maven 将整个 lib 目录(包含 JavaFX 库和 aspectJ/spring 工具 java 代理)捆绑在 jar 中?这样做可以解决我部署应用程序时必须随身携带该 lib 文件夹的问题!谢谢!

******编辑******

我弄乱了 spring boot maven 插件选项,不幸的是我的 jar 仍然不包含我的文件夹:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <folders>
            <folder>lib</folder>
        </folders>
        <agent>lib/aspectjweaver-1.9.5.jar</agent>
        <agent>lib/spring-instrument-5.2.3.RELEASE.jar</agent>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>

******编辑 2******

我刚刚发现了一个很棒的库,它通过让您在运行时以编程方式加载它们来完全消除对 -javaagent 参数的需求。看起来我的类路径上的 AspectJ 和 Spring-Instrument 的存在也是它所需要的!看看:https://github.com/subes/invesdwin-instrument.

我现在需要的只是以某种方式将 JavaFX 运行时捆绑到我的 jar 中,而不是使用命令行参数从外部引用它。

【问题讨论】:

  • 问题是,这不是项目依赖。这些是 Maven 不知道的外部文件,仅在运行时提供。
  • 究竟缺少哪些文件?
  • 回答您的第一个问题,这些文件不是由 Maven 作为依赖项提供的,它们是与 openJDK (openJFX) 分开提供的。这些文件过去直接捆绑在 JRE 中,但自 Java 11 起不再存在,因此必须以这种方式引用它们。
  • 不需要SDK。 Maven Central 中的工件包含您需要的所有代码(包括特定于平台的本机代码,在运行时提取)。如果您的主类是您的Application 实现并且javafx.graphics 模块正在从classpath 使用,那么您遇到的错误也可能发生。如果使用类路径中的所有内容(可能带有胖 jar),那么您的主类 不能Application 的子类。请参阅this answer(尤其是编辑)和我在之前评论中链接到的答案。

标签: java spring maven javafx libraries


【解决方案1】:

警告:由于 fat/uber JAR 可能会导致 JavaFX 被放置在类路径中,请注意这种方法 is not supported

不要使用 JavaFX SDK,而是在 pom.xml 文件中声明您对 JavaFX 的依赖。然后您可以使用maven-shade-plugin 创建一个可执行的 fat/uber JAR。从 Maven Central 下载的适当 JavaFX JAR(例如图形 JAR 文件)嵌入了所需的平台特定本机代码,这些代码将在运行时提取(例如,到用户主目录)。

这是一个最小的例子:

Launcher.java

package com.example;

import javafx.application.Application;

public class Launcher {

  public static void main(String[] args) {
    Application.launch(App.class, args);
  }
}

App.java

package com.example;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class App extends Application {

  @Override
  public void start(Stage primaryStage) {
    StackPane root = new StackPane(new Label("Hello, World!"));
    primaryStage.setScene(new Scene(root, 500, 300));
    primaryStage.show();
  }
}

pom.xml

<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>com.example</groupId>
    <artifactId>javafx-uber-jar</artifactId>
    <version>1.0</version>

    <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <maven.compiler.source>13</maven.compiler.source>
      <maven.compiler.target>13</maven.compiler.target>
    </properties>

    <build>
      <plugins>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.1</version>
          <configuration>
              <release>13</release>
          </configuration>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-shade-plugin</artifactId>
          <version>3.2.2</version>
          <executions>
            <execution>
              <phase>package</phase>
              <goals>
                <goal>shade</goal>
              </goals>
              <configuration>
                <transformers>
                  <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                    <mainClass>com.example.Launcher</mainClass>
                  </transformer>
                </transformers>
              </configuration>
            </execution>
          </executions>
        </plugin>

      </plugins>
    </build>

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

</project>

命令行:

mvn package

以上将创建一个特定于平台的 uber JAR。有关如何创建跨平台 uber JAR 的想法,请参阅 this answer

根据您用于开发应用程序的 Java 版本,您可以查看jlink(Java 9+)和/或jpackage(Java 14,早期访问)作为创建胖子的替代方法/uber JAR 文件。如果您使用其中之一,请考虑使用 JavaFX 的 JMOD 文件(可以是 found here),因为它配置自定义图像以更好地处理本机代码(即不提取)。


请注意,主类不是Application 的子类。这对于将 JavaFX 库放在 classpath 上的应用程序是强制性的,至少对于 JavaFX 9-13 来说是这样。这个要求的原因与允许 JavaFX 应用程序没有 main 方法的实现有关。如果javafx.graphics 模块不在 modulepath 上,则假定“JavaFX 组件丢失”。但这只发生在主类和Application 类相同时,因此上述解决方法。

【讨论】:

    猜你喜欢
    • 2014-06-26
    • 2016-07-20
    • 1970-01-01
    • 2012-11-01
    • 2011-01-17
    • 2015-10-21
    • 2023-03-05
    • 2016-10-17
    相关资源
    最近更新 更多