我正在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);
}
}
答案 0 :(得分:3)
我会避免在静态初始化器中创建JavaFX小部件(例如静态字段或静态块),因为这会在加载类时创建它们,这可能发生在任何线程中< / strong>即可。您希望在JavaFX Application Thread中实现这一点 在你的情况下,它发生在主线程中,这肯定是不正确的。
检查this answer以获取有关JavaFX应用程序启动的更多详细信息,以及线程如何参与该过程。
尝试在“JavaFX应用程序线程”之外初始化JavaFX小部件是(据我所知)未定义的行为,并且可能以许多不同的方式失败(或通过运气成功)。如果该创建失败,则类加载失败(因为静态init失败),因此“找不到类”。不幸的是,由于这在加载主类时发生,你不会看到初始错误,只是“找不到类XXX”。
可能在你的情况下,java
启动器可以很好地处理这个初始化,但你的.exe使用的启动器是不同的。我没有太惊讶它失败了。我同样感到惊讶它适用于常规java:)