【问题标题】:How to package a javafx11/jdk11 application using NetBeans 10如何使用 NetBeans 10 打包 javafx11/jdk11 应用程序
【发布时间】:2019-04-07 14:19:03
【问题描述】:

在远离 Java 世界一段时间后,我正在尝试在 NetBeans 10 中使用 javafx11、jdk11 打包 javafx 应用程序。由于 Javafx 被排除在标准 jdk 之外,而 NetBeans 仍在 Apache 中孵化,因此事情比以前更艰难了。

幸运的是,我找到了this great tutorialthis great answer,这让我可以在 NetBeans 中运行一个简单的 Hello World 应用程序。

但我不能让它在 IDE 之外工作:当使用输出的 jar 调用时,jre 会出现以下错误:

java.lang.NoClassDefFoundError: javafx/application/Application

所以我想我需要在 jar 中打包一个 javafx 运行时才能运行它,但我不知道该怎么做。

我找到了一些指针,但它们都使用命令行指向 javafx sdk,但我的目标不是安装了这个 sdk 的机器,而是希望将所有需要的东西(除了 jre 本身)打包到 jar 中。

非常感谢任何帮助。

【问题讨论】:

  • 感谢您指出,事实上我做到了,问题是我对此有点不知所措:您指向教程的另一部分似乎并没有创建一个胖子-jar (“但是,如果您想使用 java 命令运行模块化应用程序,则需要 JavaFX SDK”)并且答案的另一部分似乎是指“模块化应用程序”,它似乎捆绑了整个 jdk,这不是什么我在找。抱歉,您很愚蠢,您显然是该主题的大师。
  • 如果您有一个非模块化项目并且您不使用构建工具(Maven、Gradle),本教程将准确地展示如何为您的平台创建一个 fat-jar,甚至是一个跨平台平台脂肪罐。这不是最好的解决方案,但您仍然可以做到。
  • 好的,我找到了相关部分。我想我可以尝试自定义 Ant 目标来执行这些命令。
  • 试过了,它不起作用:如果我运行 jar,它会给出错误消息“错误:找不到或加载主类 hellofx.launcher”所以我将主类更改为“HelloFX " 然后我收到错误 "JavaFX 运行时组件丢失..."。这些命令的问题在于,虽然它们有帮助,但它们并没有真正解释如何打包所述运行时组件。如果我可以简单地被告知罐子里应该是什么以及它应该在哪里,我会自己弄清楚该怎么做,但只有一系列神奇的公式,如果没有,我会迷路不行。

标签: java javafx netbeans


【解决方案1】:

我在很大程度上要感谢 José Pereda 的无价帮助(以及他的 cmets 值得称赞的耐心)。所以应该归功于他。

那么,我们开始吧:

你的目标是什么

您的 jar 必须符合以下规范:

  1. 它必须包含 javafx jar 库(表示它们的包文件夹,从它们的 jar 中提取并放在您的根目录中)。
  2. 它必须在根目录包含二进制 javafx 库(Linux 为 *.so)。
  3. 它必须(非常重要)有一个启动器:一个不扩展“应用程序”的主类。如果没有,错误将不清楚:它会告诉它找不到 javafx 运行时;这不是真正的问题。

现在,如果您可以通过任何方式(Ant、Makefile、自定义脚本、特定 IDE 功能...)做到这一点,那么一切都会很好地工作。

如何在 NetBeans(和其他使用 Ant 的地方,稍作修改)中做到这一点

首先,我在我的项目中创建了一个 lib 文件夹并将库直接放在那里(这不是必需的,在我的情况下更简单),然后我在 build.xml 中覆盖了“post-jar”目标,添加接下来创建第二个“dist”存储库,我称之为“dist-portable”并在其中构建了 fat jar:

<target name="-post-jar">

<property name="store.jar.name" value="${application.title}${application.desc}-portable"/>
<property name="store.dir" value="dist-portable"/>
<property name="store.jar" value="${store.dir}/${store.jar.name}.jar"/>

<echo message="Packaging ${application.title}${application.desc} into a single JAR at ${store.jar}"/>
    
    <delete dir="${store.dir}"/>
    <mkdir dir="${store.dir}"/>

    
    <jar destfile="${store.dir}/temp_final.jar" filesetmanifest="skip">
        <zipgroupfileset dir="dist" includes="*.jar"/>
        <zipgroupfileset dir="lib" includes="*.jar"/>
        <fileset dir="lib" includes="*.so"/>

        <manifest>
            <attribute name="Main-Class" value="${main.class}"/>
        </manifest>
    </jar>

    <zip destfile="${store.jar}">
        <zipfileset src="${store.dir}/temp_final.jar"
        excludes="META-INF/*.SF, META-INF/*.DSA, META-INF/*.RSA"/>
    </zip>

<delete file="${store.dir}/temp_final.jar"/>

</target>

替代解决方案

使用更高级的构建工具,例如 Maven 或 Gradle。我不想(因此我的问题的重点),因为考虑到我只在做小项目,它们看起来太复杂了,不值得费心。

更具争议的替代解决方案

“8”代(NetBeans 8、Javafx8 和 JDK8)是很棒的软件,发布时间不早(2014 年上半年),直到几个月前才正式支持:它们不是ancient 并且......他们只是开箱即用,无需做任何事情。 “11”一代可能需要成熟一点,我认为还没有每个环境都跳到最前沿的 JDK11。 旧版本仍然可以在任何地方找到并且运行良好,您可以考虑简单地使用它们。请注意它们不再更新(这可能是一个安全问题)。

【讨论】:

  • 干得好!正如您所提到的,必须将 JavaFX SDK 文件复制到 lib 文件夹不是很方便,这可以是绝对路径。而且你可以让它跨平台,因为现在它只能在 Linux 上运行。下载其他平台的 SDK,并将它们也添加到 jar(类和本机库)中。虽然我现在不推荐胖罐子,但我认为它仍然有用。
【解决方案2】:

一个月前我遇到了同样的问题。为了解决这个问题,我将 Maven 与以下 pom.xml 一起使用:

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>{your-groupId}</groupId>
<artifactId>{your-artifactId}</artifactId>
<version>0.1-SNAPSHOT</version>

<properties>
    <lwjgl.version>3.2.1</lwjgl.version>
    <joml.version>1.9.12</joml.version>
    <main.class>{your-package-name}.{your-main-class}</main.class>
    <maven.compiler.source>1.11</maven.compiler.source>
    <maven.compiler.target>1.11</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<!-- // Compiling : $ mvn clean compile assembly:single-->

<build>
    <directory>outputDirectory</directory>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.1.0</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>false</addClasspath>
                        <mainClass>${main.class}</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>${main.class}</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
        </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>
            </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>${main.class}</mainClass>
            </configuration>
        </plugin>
    </plugins>
    <resources>
        <resource>
            <directory>src/main/java/{your-package-name}</directory>
            <includes>
                <include>sample.fxml</include>
            </includes>
        </resource>
    </resources>
</build>

<dependencies>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-base</artifactId>
        <version>13-ea+2</version>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-controls</artifactId>
        <version>13-ea+2</version>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-fxml</artifactId>
        <version>13-ea+2</version>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-graphics</artifactId>
        <version>13-ea+2</version>
    </dependency>
    <dependency>
        <groupId>javax.json</groupId>
        <artifactId>javax.json-api</artifactId>
        <version>1.1.4</version>
    </dependency>
</dependencies>

您可以找到所有可用 javafx 工件的列表here

你所要做的就是:

  • 将 pom.xml 添加到您的项目中
  • 检查依赖项是否符合您的需求
  • 导入 pom.xml(NetBeans 肯定会向您推荐)
  • 添加文件 module-info.java。我的内容如下:

    module {your-package-name} {
    
        requires javafx.fxml;
        requires javafx.controls;
        requires javafx.graphics;
        requires javafx.base;
        requires javax.json;
        // Change the list to match your dependencies
    
        opens {your-package-name};
    
    }
    
  • 使用 NetBeans 或通过终端中的 mvn compile assembly:single 命令构建您的 jar

【讨论】:

  • 感谢您的帮助,但我宁愿不使用 Maven。既然它为您工作,这意味着它是可能的:您是否知道如何在 Ant 或标准 NetBeans 项目属性中做同样的事情?
  • 一开始和你一样,并不想用Maven,可惜除了SDK,我还没有找到一个jvafx编译的jar。然后我决定使用 Maven。对于 Ant,我真的不知道它是如何工作的,所以帮不了你:/
  • 我找到了,如果您对这个问题仍然感兴趣,可以查看我的回答。
猜你喜欢
  • 2019-05-30
  • 2019-08-10
  • 1970-01-01
  • 1970-01-01
  • 2019-10-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-11
  • 2015-06-27
相关资源
最近更新 更多