【发布时间】:2010-09-07 03:53:57
【问题描述】:
在编写Java应用程序时,由于各种原因调用System.exit是不受欢迎的,那么如何通知调用进程并非一切都按计划进行?
编辑: 1 是standin,用于任何非零退出代码。
【问题讨论】:
在编写Java应用程序时,由于各种原因调用System.exit是不受欢迎的,那么如何通知调用进程并非一切都按计划进行?
编辑: 1 是standin,用于任何非零退出代码。
【问题讨论】:
当“应用程序”实际上是大型 Java 应用程序(服务器)的子应用程序(例如 servlet、applet)时,不赞成使用 System.exit:在这种情况下,System.exit 可以停止 JVM 并因此所有其他子应用程序也是如此。在这种情况下,抛出一个适当的异常,可以被应用程序框架/服务器捕获和处理是最好的选择。
如果 java 应用程序真的要作为独立应用程序运行,那么使用System.exit 没有任何问题。在这种情况下,设置退出值可能是向父进程传达失败或成功的最简单(也是最常用)的方式。
【讨论】:
System.exit()时如何确保关闭打开的资源?
我同意“抛出异常”的观点。一个原因是,如果您希望其他代码能够使用它,调用 System.exit 会使您的代码难以使用。例如,如果您发现您的类在 Web 应用程序或某种消息消费应用程序中很有用,那么最好让这些容器有机会以某种方式处理故障。容器可能想要重试操作、决定记录并忽略问题、向管理员发送电子邮件等。
您的main() 方法是一个例外;这可能会捕获异常,并使用调用进程或 shell 脚本可以识别的某个值调用 System.exit()。
【讨论】:
System.exit() 将阻塞,如果启动它的线程被用于关闭钩子,则会产生死锁。
【讨论】:
我们公司的政策是可以(甚至首选)调用 System.exit(-1),但仅限于 init() 方法。在程序的正常流程中调用它之前,我肯定会三思而后行。
【讨论】:
我认为抛出异常是出现问题时应该做的。这样,如果您的应用程序没有作为独立应用程序运行,则调用者可以对其做出反应并获得一些有关问题所在的信息。它也更容易用于调试目的,因为当您看到堆栈跟踪时,您也可以更好地了解出了什么问题。
需要注意的重要一点是,当异常到达顶层并因此导致 VM 退出时,VM 返回返回码 1,因此使用该返回码的外部应用程序会看到出现问题。
我认为 System.exit() 唯一有意义的情况是,当您的应用程序旨在由非 Java 应用程序调用时,因此必须使用返回码来查看您的应用程序是否工作并且您想要这些应用程序有机会对不同的问题做出不同的反应,即您需要不同的返回码。
【讨论】:
在 web servlet 环境中也可能很危险/有问题。
抛出异常通常被认为是另一种选择。
【讨论】:
抛出异常是将有关特定错误的信息发送到应用程序之外的最佳方式。
一个数字并不能告诉你:
Exception at thread 'main': FileNotFoundException "The file 'foo' doesn't exist"
(或类似的东西)
【讨论】:
对于 正常 退出不赞成。如果“并非一切都按计划进行”,那么 System.exit 就可以了。
更新:我应该补充一点,我假设您的“1”具有记录在某处的含义。
【讨论】:
我也觉得有必要添加一些我的盐。这是一个很好的问题,在我编写应用程序时总是会弹出。
这里的每个人似乎都同意,你应该小心使用System.exit(),如果可能的话,使用异常。但是,System.exit() 似乎仍然是向系统返回基本信息的唯一方法,因此如果您想让您的应用程序可编写脚本,则需要这样做。如果您不需要它,只需抛出一个异常并完成它。
但如果(且仅当)您的应用程序是单线程的,那么使用它就可以了——保证没有其他东西进入,并且没有资源是打开的(至少如果您一直使用 @987654321 @ idiom,我强烈推荐它,因为它还使代码更简洁)。
另一方面,一旦您的应用程序创建了任何类型的可能写入资源的线程,System.exit() 就完全“不,不”,因为它可能(并且随着时间的推移会)损坏数据.
为了能够使用多线程和脚本应用程序并仍然保证数据完整性,我目前最好的解决方案是保存您创建的任何资源修改线程(例如,始终使用添加线程的工厂方法到列表中),并且还安装了一个关闭钩子,通过中断和加入它来干净地结束每个线程。由于System.exit() 也调用了关闭钩子,这将保证(减去编程错误)在资源写入过程中没有线程被杀死。
哦,是的,也许我什至不应该提及它,但是:永远,永远,使用那种可怕的 System.halt() 方法。它只是在头部射击虚拟机,而不调用任何关闭挂钩。
【讨论】: