关于java:System.exit的替代品(1)

关于java:System.exit的替代品(1)

Alternatives to System.exit(1)

由于各种原因,在编写Java应用程序时都不愿调用System.exit,所以如何通知调用过程并非一切都按计划进行?

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


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

如果确实要将Java应用程序作为独立的应用程序运行,则使用System.exit并没有错。在这种情况下,设置退出值可能是将失败或成功传达给父进程的最简单(也是最常用的方式)。


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

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


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


我认为抛出异常是您在出现问题时应该采取的措施。这样,如果您的应用程序未作为独立应用程序运行,则调用者可以对此应用程序做出反应并获得有关发生问题的信息。它也更易于调试,因为您还可以更好地了解堆栈跟踪时出了什么问题。

需要注意的重要一件事是,当异常达到最高级别并导致VM退出时,VM返回的返回码为1,因此使用该返回码的外部应用程序会发现出了问题。

我认为System.exit()有意义的唯一情况是,您的应用程序应由非Java的应用程序调用,因此必须使用返回码来查看您的应用程序是否正常工作,而您想要这些应用程序有机会对不同的错误做出不同的反应,即您需要不同的返回码。


我们公司的政策是可以(即使首选)调用System.exit(-1),但只能使用init()方法。在程序正常流程中调用它之前,我肯定会三思。


抛出异常是向上和向应用程序外发送有关特定错误的信息的最佳方法。

一个数字并不能告诉您以下信息:

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

(或接近它的地方)


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

引发异常通常被认为是另一种选择。


我也被迫补充一些salt。这是一个很棒的问题,在我编写应用程序时总是弹出。

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

但是,如果(并且仅当)您的应用程序是单线程的,那么使用它就可以了-可以确保没有其他东西进入,也没有资源打开(至少如果您始终使用try- with-resource惯用语,我强烈建议您这样做,因为它也使代码更简洁,更紧凑)。

另一方面,一旦您的应用程序创建了任何类型的可能写入资源的线程,System.exit()便总计为" no,no",因为它可能(并且随着时间的推移)会破坏数据。 。

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

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


正常退出时,皱着眉头。如果"并非一切都按计划进行",那么System.exit很好。

更新:我要补充一点,我假设您的" 1"具有某处记录的含义。


推荐阅读