JavaFX native 打包 - 初始化静态变量时出现奇怪的错误

标签 java javafx exe native packaging

我正在 Netbeans 中开发一个 JavaFX 项目,该项目目前大约有 3000 行长,我定期将其打包为 .exe 进行测试,但从未遇到过像这个奇怪事件这样的问题。

当本地打包为 Windows .exe 文件时,我发现在安装 .exe 并启动我的程序后,我收到一个弹出窗口,显示“未找到类 {mypackage}/{mymainclass}。 ”后跟“无法启动 JVM。

在 Netbeans 中启动该程序,打包为 .exe,并使用“java -jar {app}.jar”在 Powershell 中启动 .jar,都完全没有错误。即使已安装的应用程序文件夹中的 .jar 也很好,命令行上没有错误。

经过几个小时的 git 提交和本地打包后,我成功地将问题追溯到一行代码: private static ComboBox choices = new ComboBox();

当我在初始化程序中初始化 ComboBox 时,该程序在从 .exe 安装后神奇地工作了:

private static ComboBox choices;
{
    choices = new ComboBox();
}

但是,当我使用静态初始化程序(通过将 static 放在第一个大括号前面)时,即使 Netbeans 声明“初始化程序可以是静态的”,我也会收到与以前相同的错误。

这令人费解,因为 Java 显然对代码本身没问题,但在通过 native 打包程序后,它无法启动。我已经使用了大量类似的代码行来初始化其他类中的静态变量,没有产生任何不良影响。

我尝试在主类中添加类似的行:private static CheckBox chkbox = new CheckBox();

安装 .exe 后,它导致了完全相同的错误(和以前一样,.jar 没问题),但是当我将该行剪切并粘贴到不同的类时,它没有任何效果。

有趣的是,我的主类已经有一个静态 boolean 值,其初始化方式与 ComboBox 和 CheckBox 相同: private static boolean someBool = true;但 boolean 值不会导致任何问题。

谁能解释一下这背后的原因吗?谢谢。

编辑:我也尝试在另一台机器上打包,但在相同的 git 提交后它停止工作。 我使用的是 1.8.0_144 版本的 JDK 和 JRE。

编辑2:这是一个产生错误的简单示例的主类。

package testproject;

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

public class MainApplication extends Application {

    private static CheckBox testCheckBox = new CheckBox(); // Causes error after launching from installed .exe

    /* UNCOMMENT THIS SECTION AND REMOVE THE " = new CheckBox()" ABOVE TO FIX THE ERROR
    {
        testCheckBox = new CheckBox();
    }
     */

    @Override
    public void start(Stage primaryStage) {
        StackPane root = new StackPane();
        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Empty window");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

}

最佳答案

我会避免在静态初始化程序中创建JavaFX小部件(例如静态字段或静态 block ),因为这会在加载类时创建它们,这可能在任何线程中发生。您希望在 JavaFX 应用程序线程中发生这种情况。
在您的情况下,它发生在主线程中,这绝对是不正确的。

检查this answer有关 JavaFX 应用程序启动以及线程如何参与该过程的更多详细信息。

尝试在“JavaFX应用程序线程”之外初始化JavaFX小部件是(据我理解)未定义的行为,并且可能以多种不同的方式失败(或者幸运地成功)。如果创建失败,则类加载失败(因为静态初始化失败),因此“找不到类”。不幸的是,由于这种情况发生在加载主类时,您看不到最初的错误,只是“找不到类 XXX”。

可能在您的情况下,java启动器可以很好地处理此初始化,但 .exe 使用的启动器是不同的。我对它的失败并不感到太惊讶。我同样惊讶它可以与常规 java 一起使用:)

关于JavaFX native 打包 - 初始化静态变量时出现奇怪的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46084756/

相关文章:

java - org.postgresql.util.PSQLException : The column index is out of range: 2, 列数:1

java - Android:使用 MediaRecorder 中的 getMaxAmplitude(),同时使用 TarsosDSP 中的 PercussionOnsetDetector

java - 在 JavaFX 中使用 Map 和 TableView

python - 是否可以在 Vista 上构建 exe 并使用 py2exe 在 XP 上部署

python - 我正在使用 PyInstaller 将 .py 文件转换为 .exe 文件,但我遇到了困难?

java - 粗线防止变形

java - 在 JBoss 中的 JNDI 树上保留字节数组

javafx - 工具提示背景(使用 JavaFX CSS)

javafx - 为什么 -fx-border-color 重置 TextField 的边框半径?

java - Eclipse 不导出外部 jar 库