当前位置: 首页 > 知识库问答 >
问题:

如何将JavaFX SDK直接捆绑在输出jar中?

蒯宇定
2023-03-14

目前,我在启动我的程序时使用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工具在我的类路径上的存在也是它所需要的!过来看:https://github.com/subes/invesdwin-instrument.

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

共有1个答案

万涵亮
2023-03-14

警告:由于胖/uber JAR可能会导致JavaFX被放置在类路径上,请注意不支持这种方法。

与其使用JavaFX SDK,不如在pom.xml文件中声明您对JavaFX的依赖。然后您可以使用maven-shade-plugin创建一个可执行的胖/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

以上内容将创建一个特定于平台的优步JAR。关于如何创建跨平台uber JAR的想法,请参见此答案。

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

请注意,主类不是应用程序的子类。对于将JavaFX库放在类路径上的应用程序,至少对于JavaFX 9-13来说,这是强制性的。这一要求的原因与允许JavaFX应用程序没有主方法的实现有关;如果使用javafx。图形模块不在模块路径上,假设“JavaFX组件缺失”。但是,只有当主类和应用程序类相同时,才会发生这种情况,因此采用了上述解决方法。

 类似资料:
  • 问题内容: 我做了一个Java应用程序。并将所有类捆绑在jar文件中。.我从netbeans运行项目,我的应用程序运行成功..但是我将我的.jar文件放在另一个地方,然后从那里运行..我没有我的应用程序使用的图标..在代码中,我从项目文件夹中存在的images目录中获取我的图标。 现在,我想知道如何将这些图像文件呈现给最终用户(就像我们呈现.jar文件一样)。 问题答案: 似乎这里有两个问题: 在

  • 如何让gradle将一些依赖项作为jar包含到模块结果jar中?i、 e.在文件夹中使用嵌套jar制作jar? 这不是Android项目,多模块项目中的许多模块都应该这样做,所以类似fatJar、uberJar和shadowJar的解决方案似乎不适合。

  • 我创建了一个Java应用程序,它使用运行库执行Python脚本。我想知道是否有一种方法可以将Python.exe和必需的库包含在Jar文件中?

  • 我制作了一个javafx应用程序表单,我得到了一个可执行的jar作为输出。现在,我的javafx应用程序依赖于两个第三方JAR,比如commons。伊奥。2.4.罐子 目前,为了运行我的应用程序,我必须像这样将这些依赖jar保存在可执行jar的类路径中 但我希望所有依赖的jar都捆绑在我的可执行jar中。 因为javafx使用ant构建,所以我尝试使用 但是在捆绑了所有依赖的jar之后,我没有得到

  • 好的,我在分发我的邮件时遇到了一些问题。jar文件。当我只是从NetBeans运行程序时,它可以工作,但是如果我尝试从dist文件夹运行它,它就不工作(没有图像被加载)。 以下是我的程序的层次结构: src/img/随机图像 src/myapp/源文件 我用这个函数加载图像: 在那之后: 在我构建我的项目之后,这些图像在jar文件中,但是它们没有被加载。你知道为什么吗?

  • 问题内容: 我想要在一个JAR文件中具有本机库,JNI库和所有Java API类,以避免重新分配的麻烦。 似乎在GitHub上有尝试,但是 1. 2. 它不包括实际的本机库,仅包括JNI库。 3. 它似乎特定于Leiningen的本机依赖插件(它不能作为可再发行组件使用)。 问题是,我可以将所有内容捆绑在一个JAR中并重新分发吗?如果是,怎么办? PS:是的,我意识到这可能会带来可移植性。 问题答