Javafx本机包装 - 初始化静态变量的奇异误差



我正在研究Netbeans中的Javafx项目,该项目目前长约3000行,我经常打包作为.EXE进行测试,但从未遇到过这样的好奇事件的问题。

当作为Windows .exe文件本地包装时,我发现安装.exe并启动程序后,我会得到一个弹出窗口,说" class {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显然对代码本身很好,但是在通过本机封装器之后,它不会启动。我使用了许多类似的代码线来初始化其他类中的静态变量,没有任何不良影响。

我尝试在主类中添加类似的行: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);
    }
}

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

检查此答案以获取有关Javafx应用程序启动的更多详细信息,以及该过程中的线程如何涉及。

试图在" Javafx应用程序线程"之外初始化Javafx窗口小部件是(对我的理解)不确定的行为,并且可能以许多不同的方式失败(或通过运气成功)。如果该创建失败,则类加载失败(因为静态init失败),因此"找不到类"。不幸的是,由于这是在加载主类时发生的,因此您不会看到初始错误,只有"找不到类XXX"。

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

最新更新