Java中什么时候应该调用System.exit
在Java中,以下代码中带或不带System.exit(0)
有什么区别?
public class TestExit
{
public static void main(String[] args)
{
System.out.println("hello world");
System.exit(0); // is it necessary? And when it must be called?
}
}
文档 说: “这个方法永远不会正常返回。”这是什么意思?
In Java, What is the difference with or without System.exit(0)
in following code?
public class TestExit
{
public static void main(String[] args)
{
System.out.println("hello world");
System.exit(0); // is it necessary? And when it must be called?
}
}
The document says: "This method never returns normally." What does it mean?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
System.exit()
可用于运行 在程序退出之前关闭挂钩。这是处理大型程序中关闭的便捷方法,其中程序的所有部分不能(也不应该)相互了解。然后,如果有人想要退出,他可以简单地调用 System.exit(),关闭挂钩(如果设置正确)会负责执行所有必要的关闭仪式,例如关闭文件、释放资源等等“这个方法永远不会正常返回。”意味着该方法不会返回;一旦线程到达那里,它就不会再回来。
另一种可能更常见的退出程序的方法是简单地到达
main
方法的末尾。但如果有任何非守护线程正在运行,它们将不会被关闭,因此 JVM 也不会退出。因此,如果您有任何此类非守护线程,则需要一些其他方法(而不是关闭挂钩)来关闭所有非守护线程并释放其他资源。如果没有其他非守护线程,从main
返回将关闭 JVM 并调用关闭挂钩。由于某种原因,关闭挂钩似乎是一种被低估和误解的机制,人们正在用各种专有的自定义黑客来重新发明轮子来退出他们的程序。我鼓励使用关闭挂钩;这一切都在标准运行时中反正都会用
System.exit()
can be used to run shutdown hooks before the program quits. This is a convenient way to handle shutdown in bigger programs, where all parts of the program can't (and shouldn't) be aware of each other. Then, if someone wants to quit, he can simply callSystem.exit()
, and the shutdown hooks (if properly set up) take care of doing all necessary shutdown ceremonies such as closing files, releasing resources etc."This method never returns normally." means just that the method won't return; once a thread goes there, it won't come back.
Another, maybe more common, way to quit a program is to simply to reach the end of the
main
method. But if there are any non-daemon threads running, they will not be shut down and thus the JVM will not exit. Thus, if you have any such non-daemon threads, you need some other means (than the shutdown hooks) to shut down all non-daemon threads and release other resources. If there are no other non-daemon threads, returning frommain
will shut down the JVM and will call the shutdown hooks.For some reason shutdown hooks seem to be an undervalued and misunderstood mechanism, and people are reinventing the wheel with all kind of proprietary custom hacks to quit their programs. I would encourage using shutdown hooks; it's all there in the standard Runtime that you'll be using anyway.
在这种情况下,就不需要了。不会启动额外的线程,您不会更改退出代码(默认为 0) - 基本上这是没有意义的。
当文档说该方法永远不会正常返回时,这意味着后续代码行实际上无法访问,即使编译器不知道:
要么抛出异常,要么虚拟机将终止返回之前。它永远不会“只是回来”。
很少有值得调用
System.exit()
IME 的情况。如果您正在编写命令行工具,并且您想通过退出代码指示错误而不是仅仅抛出异常,那么这是有意义的......但我不记得上次在正常生产代码中使用它是什么时候。In that case, it's not needed. No extra threads will have been started up, you're not changing the exit code (which defaults to 0) - basically it's pointless.
When the docs say the method never returns normally, it means the subsequent line of code is effectively unreachable, even though the compiler doesn't know that:
Either an exception will be thrown, or the VM will terminate before returning. It will never "just return".
It's very rare to be worth calling
System.exit()
IME. It can make sense if you're writing a command line tool, and you want to indicate an error via the exit code rather than just throwing an exception... but I can't remember the last time I used it in normal production code.该方法永远不会返回,因为这是世界末日,接下来不会执行任何代码。
在您的示例中,您的应用程序无论如何都会在代码中的同一位置退出,但是,如果您使用 System.exit。您可以选择将自定义代码返回到环境中,例如
谁将使用您的退出代码?调用应用程序的脚本。适用于 Windows、Unix 和所有其他可编写脚本的环境。
为什么要返回代码?说“我没有成功”、“数据库没有回答”之类的话。
要了解如何获取退出代码的值并在 unix shell 脚本或 windows cmd 脚本中使用它,您可以检查 此网站上的此答案
The method never returns because it's the end of the world and none of your code is going to be executed next.
Your application, in your example, would exit anyway at the same spot in the code, but, if you use System.exit. you have the option of returning a custom code to the enviroment, like, say
Who is going to make use of your exit code? A script that called the application. Works in Windows, Unix and all other scriptable environments.
Why return a code? To say things like "I did not succeed", "The database did not answer".
To see how to get the value od an exit code and use it in a unix shell script or windows cmd script, you might check this answer on this site
System.exit(0)
终止 JVM。在这样的简单示例中,很难察觉其中的差异。该参数被传回操作系统,通常用于指示异常终止(例如某种致命错误),因此如果您从批处理文件或 shell 脚本调用 java,您将能够获取该值并了解一下如果申请成功。如果您在部署到应用程序服务器的应用程序上调用
System.exit(0)
,将会产生相当大的影响(在尝试之前请考虑一下)。System.exit(0)
terminates the JVM. In simple examples like this it is difficult to percieve the difference. The parameter is passed back to the OS and is normally used to indicate abnormal termination (eg some kind of fatal error), so if you called java from a batch file or shell script you'd be able to get this value and get an idea if the application was successful.It would make a quite an impact if you called
System.exit(0)
on an application deployed to an application server (think about it before you try it).在可能具有复杂关闭挂钩的应用程序中,不应从未知线程调用此方法。
System.exit
永远不会正常退出,因为该调用将阻塞,直到 JVM 终止。就好像任何正在运行的代码在完成之前都已拔掉电源插头一样。调用 System.exit 将启动程序的关闭挂钩,并且调用 System.exit 的任何线程都将阻塞,直到程序终止。这意味着如果关闭挂钩又向调用 System.exit 的线程提交任务,则程序将死锁。我在我的代码中使用以下内容处理这个问题:
In applications that may have complex shutdown hooks, this method should not be called from an unknown thread.
System.exit
never exits normally because the call will block until the JVM is terminated. It's as if whatever code is running that has the power plug pulled on it before it can finish. CallingSystem.exit
will initiate the program's shutdown hooks and whatever thread that callsSystem.exit
will block until program termination. This has the implication that if the shutdown hook in turn submits a task to the thread from whichSystem.exit
was called, the program will deadlock.I'm handling this in my code with the following:
虽然答案确实很有帮助,但有些人错过了一些更多的额外细节。除了上面的答案之外,我希望下面的内容能够帮助理解java中的关闭过程:
已开始。如果任何应用程序线程(守护程序或非守护程序)仍在运行
在关闭时,它们继续与关闭过程同时运行。
如果 runFinalizersOnExit 为 true,则停止。
PS:JVM 可以以有序或突然方式关闭。
JVM要关闭,也可以通过调用Runtime.halt来突然关闭
或者通过操作系统杀死 JVM 进程(例如发送
信号杀死)。
Though answer was really helpful but some how it missed some more extra detail. I hope below will help understand the shutdown process in java, in addition to the answer above:
are started. If any application threads (daemon or nondaemon) are still running
at shutdown time, they continue to run concurrently with the shutdown process.
if runFinalizersOnExit is true, and then halts.
PS: The JVM can shut down in either an orderly or abrupt manner.
JVM to shut down, it can also be shut down abruptly by calling Runtime.halt
or by killing the JVM process through the operating system (such as sending a
SIGKILL).
由于以下原因,永远不要调用
System.exit(0)
:“正常”退出程序向操作系统提供与 System.exit(0) 相同的退出代码,因此它是多余的。
如果您的程序无法“正常”退出,您就失去了对开发[设计]的控制。您应该始终完全控制系统状态。
顺便说一句:如果您想指示程序异常终止,则返回 0 以外的其他返回代码确实有意义。
One should NEVER call
System.exit(0)
for these reasons:Quitting the program "normally" provides the same exit code to the operating system as
System.exit(0)
so it is redundant.If your program cannot quit "normally" you have lost control of your development [design]. You should have always full control of the system state.
By the way: Returning other return codes than 0 does make sense if you want to indicate abnormal program termination.
需要 System.exit
在您的情况下,它与简单的 return-from-main 执行完全相同的操作。
System.exit is needed
In your case, it does the exact same thing as the simple return-from-main.
Java 语言规范 说
这意味着当您有大型程序(好吧,至少比这个更大)并且想要完成其执行时,您应该使用它。
Java Language Specification says that
It means that You should use it when You have big program (well, at lest bigger than this one) and want to finish its execution.
如果您有另一个程序在 JVM 中运行并且您使用 System.exit,那么第二个程序也将被关闭。例如,假设您在集群节点上运行 java 作业,并且管理集群节点的 java 程序在同一个 JVM 中运行。如果作业使用 System.exit,它不仅会退出作业,还会“关闭整个节点”。由于管理程序已意外关闭,您将无法向该集群节点发送另一个作业。
因此,如果您希望能够从同一 JVM 中的另一个 java 程序控制您的程序,请不要使用 System.exit。
如果您想有意关闭整个 JVM,并且想利用其他答案中描述的可能性(例如关闭挂钩:Java 关闭钩子,命令行调用的非零返回值:如何在 Windows 批处理文件中获取 Java 程序的退出状态)。
另请查看运行时异常: System.exit(num) 或 throw来自 main 的 RuntimeException?
If you have another program running in the JVM and you use System.exit, that second program will be closed, too. Imagine for example that you run a java job on a cluster node and that the java program that manages the cluster node runs in the same JVM. If the job would use System.exit it would not only quit the job but also "shut down the complete node". You would not be able to send another job to that cluster node since the management program has been closed accidentally.
Therefore, do not use System.exit if you want to be able to control your program from another java program within the same JVM.
Use System.exit if you want to close the complete JVM on purpose and if you want to take advantage of the possibilities that have been described in the other answers (e.g. shut down hooks: Java shutdown hook, non-zero return value for command line calls: How to get the exit status of a Java program in Windows batch file).
Also have a look at Runtime Exceptions: System.exit(num) or throw a RuntimeException from main?