1 回答
TA贡献1825条经验 获得超6个赞
从您调用的方式来看,launch(args)
我假设,并且您后来证实了这一点,该main
方法位于Application
. 我相信这是您问题的原因。
正如您所注意到的,有很多看似 JavaFX 特定的线程正在运行。具体来说,非守护进程“JavaFX 应用程序线程”正在运行(至少,它在 Java 10 中是非守护进程)。即使该main
线程退出,该线程也会使 JVM 保持活动状态。这是 Java 的正常行为:
线程
当 Java 虚拟机启动时,通常有一个非守护线程(通常调用
main
某个指定类的方法)。Java 虚拟机继续执行线程,直到发生以下任一情况:
exit
类的方法Runtime
已被调用,安全管理器已允许退出操作发生。不是守护线程的所有线程都已死亡,无论是从对
run
方法的调用返回,还是通过抛出传播到run
方法之外的异常。
但是为什么“JavaFX 应用程序线程”在您故意不调用的情况下启动Application.launch
?我只是在这里猜测,但这可能与 JavaFX 应用程序收到的特殊待遇有关。因为至少Java的8你没有申报main
的子类中的方法Application
1。如果主类是Application
Java的子类,则自动处理启动。
import javafx.application.Application;
import javafx.stage.Stage;
public class MyApp extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
// create scene and show stage...
}
}
如果您有上述并调用java MyApp应用程序将启动并被start调用。但是,如果您有以下情况:
import javafx.application.Application;
import javafx.stage.Stage;
public class MyApp extends Application {
public static void main(String[] args) {}
@Override
public void start(Stage primaryStage) throws Exception {
// create scene and show stage...
}
}
然后main调用方法,但start就是没有。基本上,显式声明main会覆盖启动 JavaFX 应用程序的默认行为,但不会阻止 JavaFX 运行时被初始化。也许这种行为是设计好的,也可能是一种疏忽。但这里重要的是,只有当主类有一个main方法并且是一个Application子类时才会发生这种情况。如果将这两者分开:
public class MyApp extends Application {
// implement ...
}
public class Main {
public static void main(String[] args) {
// Perform pre-checks, return if necessary
Application.launch(MyApp.class, args);
}
}
那么你将不再有这个问题。
否则,您可以继续使用System.exit()或切换到Platform.exit().
还有另一种可能更合适的方法来处理这个问题。您似乎main在调用之前在方法中执行初始化Application.launch。如果在此初始化过程中出现问题,您希望中止启动 JavaFX 应用程序。好吧,JavaFX 本身提供了执行此操作的方法:Application.init().
应用程序初始化方法。在加载和构造 Application 类后立即调用此方法。应用程序可以覆盖此方法以在应用程序实际启动之前执行初始化。
Application 类提供的这个方法的实现什么都不做。
注意:此方法不会在 JavaFX 应用程序线程上调用。应用程序不得在此方法中构造场景或舞台。应用程序可以在此方法中构造其他 JavaFX 对象。
将您的初始化代码移至此方法。如果您调用,Platform.exit()则应用程序将退出并且Application.start不会被调用。另一种方法是在init. 您还可以通过使用Application.getParameters()which 返回 的实例来获取应用程序参数Application.Parameters。
public class MyApp extends Application {
@Override
public void init() throws Exception {
if (!ArgumentsHandler.handle(getParameters()) {
Platform.exit(); // or throw an exception
} else {
Storage storage = Storage.getInstance();
storage.load();
if (!storage.isLoadSuccessful()) {
Platform.exit(); // or throw an exception
}
}
}
@Override
public void start(Stage primaryStage) throws Exception {
// Create Scene and show the primary Stage
}
@Override
public void stop() throws Exception {
/*
* Called when the JavaFX application is exiting, such as from
* a call to Platform.exit(). Note, however, that in my experience
* this method is *not* called when Platform.exit() is called inside
* the "init" method. It is called if Platform.exit() is called from
* inside the "start" method or anywhere else in the application once
* it is properly started.
*
* This is where you could perform any necessary cleanup.
*/
}
}
添加回答
举报