25

由于各种原因,在编写Java ApplicationsSystem.exit时不赞成调用,那么如何通知调用进程并非一切都按计划进行?

编辑: 1 是standin任何非零退出代码的 a 。

4

9 回答 9

32

当“应用System.exit程序”实际上是较大 Java 应用程序(服务器)的子应用程序(例如 servlet、applet)时,不赞成使用 :在这种情况下,System.exit可能会停止 JVM,因此也会停止所有其他子应用程序。在这种情况下,抛出一个可以被应用程序框架/服务器捕获和处理的适当异常是最好的选择。

如果 java 应用程序真的要作为独立应用程序运行,那么使用System.exit. 在这种情况下,设置退出值可能是向父进程传达失败或成功的最简单(也是最常用)的方式。

于 2008-08-28T18:25:27.760 回答
10

我同意“抛出异常”的人群。一个原因是,如果您希望其他代码能够使用它,调用 System.exit 会使您的代码难以使用。例如,如果您发现您的类在 Web 应用程序或某种消息消费应用程序中很有用,那么最好让这些容器有机会以某种方式处理故障。容器可能想要重试操作、决定记录并忽略问题、向管理员发送电子邮件等。

您的方法是一个例外main();这可能会捕获异常,并System.exit()使用调用进程或 shell 脚本可以识别的某个值进行调用。

于 2008-08-28T18:25:11.770 回答
3

System.exit()如果启动它的线程在关闭钩子中使用,将阻塞并创建死锁。

于 2013-11-06T21:28:43.687 回答
2

我们公司的政策是可以(甚至首选)调用 System.exit(-1),但仅限于 init() 方法。在程序的正常流程中调用它之前,我肯定会三思而后行。

于 2008-08-28T17:03:15.273 回答
2

我认为抛出异常是出现问题时应该做的。这样,如果您的应用程序没有作为独立应用程序运行,则调用者可以对其做出反应并获得一些有关问题所在的信息。出于调试目的,它也更容易,因为当您看到堆栈跟踪时,您也可以更好地了解出了什么问题。

需要注意的重要一点是,当异常到达顶层并因此导致 VM 退出时,VM 返回返回代码 1,因此使用返回代码的外部应用程序会看到出现问题。

我认为 System.exit() 有意义的唯一情况是,当您的应用程序打算由非 Java 应用程序调用时,因此必须使用返回码来查看您的应用程序是否工作并且您希望这些应用程序具有有机会对不同的问题做出不同的反应,即您需要不同的返回码。

于 2008-08-29T07:57:58.667 回答
1

在 web servlet 环境中它也可能是危险的/有问题的。

抛出异常通常被认为是另一种选择。

于 2008-08-28T16:57:02.950 回答
1

抛出异常是将有关特定错误的信息发送到应用程序之外的最佳方式。

一个数字并不能告诉你:

Exception at thread 'main': FileNotFoundException "The file 'foo' doesn't exist"

(或类似的东西)

于 2008-08-28T17:05:22.447 回答
0

对于正常的出口,这是不受欢迎的。如果“并非一切都按计划进行”,那么 System.exit 就可以了。

更新:我应该补充一点,我假设您的“1”具有在某处记录的含义。

于 2008-08-28T16:53:44.843 回答
0

我也觉得有必要加点我的盐。这是一个很好的问题,在我编写应用程序时总是会弹出。

正如这里的每个人似乎都同意的那样,你应该小心使用System.exit(),如果可能的话,使用异常。然而,System.exit()这似乎仍然是向系统返回基本信息的唯一方法,因此如果您想让您的应用程序可编写脚本,则需要这样做。如果您不需要它,只需抛出一个异常并完成它。

但是,如果(且仅当)您的应用程序是单线程的,那么使用它就可以了——保证没有其他东西进入,并且没有资源是开放的(至少如果您始终使用try-with-resource成语,我强烈推荐它,因为它也使代码更简洁)。

另一方面,只要您的应用程序创建任何类型的可能写入资源的线程,System.exit() 就完全是“不,不”,因为它可能(并且随着时间的推移会)损坏数据。

为了能够使用多线程和脚本应用程序并且仍然保证数据完整性,我目前最好的解决方案是保存您创建的任何资源修改线程(例如,通过始终使用将线程添加到列表的工厂方法),并且还安装了一个关闭钩子,通过中断和加入它来干净地结束每个线程。由于也调用了关闭钩子System.exit(),这将保证(减去编程错误)在资源写入过程中不会杀死任何线程。

哦,是的,也许我什至不应该提及它,但是:永远,永远,使用那种可怕的System.halt()方法。它只是在头部射击虚拟机并且不调用任何关闭挂钩。

于 2020-03-24T07:03:25.617 回答