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

时间:2017-09-06 21:40:35

标签: java javafx exe native packaging

我正在Netbeans的一个JavaFX项目上工作,目前大约有3000行,并且我经常打包成.exe进行测试,但从来没有遇到像这个好奇的事件这样的问题。

当本地打包为Windows .exe文件时,我发现在安装.exe并启动我的程序后,我得到一个弹出窗口说&#34; Class {mypackage} / {mymainclass}找不到。< /强>&#34;然后是&#34; 无法启动JVM。&#34;

在Netbeans中启动程序,打包为.exe,并在Powershell中使用&#34; java -jar {app} .jar&#34;启动.jar。都给了绝对没有错误。即使安装的应用程序文件夹中的.jar也没问题,命令行上没有错误。

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

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

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

但是,当我使用静态初始化程序时(通过将static放在第一个大括号前面),即使Netbeans声明&#34;初始化程序可以是静态的&#34;,我得到的错误与之前。

这很令人费解,因为Java显然对代码本身很好,但是在它通过本机打包器之后它就不会启动了。我已经使用了大量类似的代码行来初始化其他类中的静态变量,没有任何不良影响。

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

在安装.exe后导致完全相同的错误(如前所述,.jar很好),但是当我将该行剪切并粘贴到另一个类时,它没有任何效果。

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

有谁可以解释这背后的原因?谢谢。

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

编辑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);
    }

}

1 个答案:

答案 0 :(得分:3)

我会避免在静态初始化器中创建JavaFX小部件(例如静态字段或静态块),因为这会在加载类时创建它们,这可能发生在任何线程中< / strong>即可。您希望在JavaFX Application Thread中实现这一点 在你的情况下,它发生在主线程中,这肯定是不正确的。

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

尝试在“JavaFX应用程序线程”之外初始化JavaFX小部件是(据我所知)未定义的行为,并且可能以许多不同的方式失败(或通过运气成功)。如果该创建失败,则类加载失败(因为静态init失败),因此“找不到类”。不幸的是,由于这在加载主类时发生,你不会看到初始错误,只是“找不到类XXX”。

可能在你的情况下,java启动器可以很好地处理这个初始化,但你的.exe使用的启动器是不同的。我没有太惊讶它失败了。我同样感到惊讶它适用于常规java:)