我们什么时候应该在 Java 中调用 System.exit

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3715967/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 03:51:23  来源:igfitidea点击:

When should we call System.exit in Java

javaexit

提问by pierrotlefou

In Java, What is the difference with or without System.exit(0)in following code?

在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? 
    }      
}

The documentsays: "This method never returns normally." What does it mean?

文件说:“这种方法从不正常返回。” 这是什么意思?

采纳答案by Joonas Pulakka

System.exit()can be used to run shutdown hooksbefore 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 call System.exit(), and the shutdown hooks (if properly set up) take care of doing all necessary shutdown ceremonies such as closing files, releasing resources etc.

System.exit()可用于在程序退出之前运行关闭挂钩。这是在较大程序中处理关闭的便捷方法,其中程序的所有部分不能(也不应该)相互了解。然后,如果有人想退出,他可以简单地调用System.exit(),并且关闭挂钩(如果设置正确)负责执行所有必要的关闭仪式,例如关闭文件、释放资源等。

"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 mainmethod. 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 from mainwill shut down the JVM and will call the shutdown hooks.

另一种可能更常见的退出程序的方法是简单地到达main方法的末尾。但是如果有任何非守护线程在运行,它们不会被关闭,因此 JVM 不会退出。因此,如果您有任何此类非守护线程,则需要一些其他方法(除了关闭挂钩)来关闭所有非守护线程并释放其他资源。如果没有其他非守护线程,则返回 frommain将关闭 JVM 并调用关闭钩子。

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 Runtimethat you'll be using anyway.

出于某种原因,关闭钩子似乎是一种被低估和误解的机制,人们正在通过各种专有的自定义黑客重新发明轮子来退出他们的程序。我鼓励使用关闭钩子;无论如何,它都包含在标准运行时中。

回答by Jon Skeet

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.

在这种情况下,它是不需要的。不会启动额外的线程,您不会更改退出代码(默认为 0) - 基本上它毫无意义。

When the docs say the method never returns normally, it means the subsequent line of code is effectivelyunreachable, even though the compiler doesn't know that:

当文档说该方法永远不会正常返回时,这意味着后续代码行实际上无法访问,即使编译器不知道:

System.exit(0);
System.out.println("This line will never be reached");

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()称得上 IME是非常罕见的。如果您正在编写命令行工具,并且您想通过退出代码指示错误而不是仅仅抛出异常,这可能很有意义……但我不记得上次在正常生产代码中使用它是什么时候了.

回答by mfx

System.exit is needed

需要 System.exit

  • when you want to return a non-0 error code
  • when you want to exit your program from somewhere that isn't main()
  • 当您想返回非 0 错误代码时
  • 当你想从不是 main() 的地方退出你的程序时

In your case, it does the exact same thing as the simple return-from-main.

在您的情况下,它与简单的从主返回完全相同。

回答by Qwerky

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.

System.exit(0)终止JVM。在像这样的简单例子中,很难看出差异。该参数被传递回操作系统,通常用于指示异常终止(例如某种致命错误),因此如果您从批处理文件或 shell 脚本中调用 java,您将能够获得此值并得到一个想法如果申请成功。

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(0)部署到应用程序服务器的应用程序(在尝试之前考虑一下),这将产生相当大的影响。

回答by mico

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

在您的示例中,您的应用程序无论如何都会在代码中的同一位置退出,但是,如果您使用 System.exit。您可以选择将自定义代码返回到环境中,例如

System.exit(42);

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.

谁将使用您的退出代码?调用应用程序的脚本。适用于 Windows、Unix 和所有其他可编写脚本的环境。

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

要查看如何获取退出代码的值并在 unix shell 脚本或 windows cmd 脚本中使用它,您可以在此站点上查看此答案

回答by Marcin Szymczak

Java Language Specificationsays that

Java 语言规范

Program Exit

A program terminates all its activity and exits when one of two things happens:

All the threads that are not daemon threads terminate.

Some thread invokes the exit method of class Runtime or class System, and the exit operation is not forbidden by the security manager.

程序退出

当发生以下两种情况之一时,程序将终止其所有活动并退出:

所有不是守护线程的线程都将终止。

某些线程调用了 Runtime 类或System类的退出方法,安全管理器不禁止退出操作。

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.

这意味着当你有大程序(好吧,至少比这个大)并想完成它的执行时,你应该使用它。

回答by djechlin

In applications that may have complex shutdown hooks, this method should not be called from an unknown thread. System.exitnever 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. Calling System.exitwill initiate the program's shutdown hooks and whatever thread that calls System.exitwill block until program termination. This has the implication that if the shutdown hook in turn submits a task to the thread from which System.exitwas called, the program will deadlock.

在可能具有复杂关闭挂钩的应用程序中,不应从未知线程调用此方法。 System.exit永远不会正常退出,因为调用将阻塞,直到 JVM 终止。就好像任何正在运行的代码在完成之前就已经拔掉了电源插头。调用System.exit将启动程序的关闭挂钩,并且调用的任何线程都System.exit将阻塞,直到程序终止。这意味着如果关闭钩子又向System.exit被调用的线程提交任务,则程序将死锁。

I'm handling this in my code with the following:

我在我的代码中使用以下方法处理此问题:

public static void exit(final int status) {
    new Thread("App-exit") {
        @Override
        public void run() {
            System.exit(status);
        }
    }.start();
}

回答by Stefan

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.

如果您有另一个程序在 JVM 中运行并且您使用 System.exit,那么第二个程序也将被关闭。例如,假设您在集群节点上运行 Java 作业,并且管理集群节点的 Java 程序在同一个 JVM 中运行。如果作业将使用 System.exit,它不仅会退出作业,还会“关闭整个节点”。由于管理程序意外关闭,您将无法向该集群节点发送另一个作业。

Therefore, do not use System.exit if you want to be able to control your program from another java program within the same JVM.

因此,如果您希望能够从同一 JVM 中的另一个 Java 程序控制您的程序,请不要使用 System.exit。

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).

如果您想故意关闭完整的 JVM 并且您想利用其他答案中描述的可能性(例如关闭钩子:Java 关闭钩子,命令行的非零返回值),请使用 System.exit调用:如何在 Windows 批处理文件中获取 Java 程序的退出状态)。

Also have a look at Runtime Exceptions: System.exit(num) or throw a RuntimeException from main?

也看看 Runtime Exceptions: System.exit(num) 或 throw a RuntimeException from main?

回答by oopexpert

One should NEVER call System.exit(0)for these reasons:

永远不要System.exit(0)因为这些原因而打电话:

  1. It is a hidden "goto" and "gotos" break the control flow. Relying on hooks in this context is a mental mapping every developer in the team has to be aware of.
  2. 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.

  3. Programming problems such as running threads that are not stopped normally become hidden.
  4. You may encounter an inconsistent application state interrupting threads abnormally. (Refer to #3)
  1. 它是一个隐藏的“goto”和“goto”打破控制流。在这种情况下依赖钩子是团队中每个开发人员都必须意识到的心理映射。
  2. “正常”退出程序会向操作系统提供相同的退出代码,System.exit(0)因此它是多余的。

    如果您的程序无法“正常”退出,您就失去了对开发 [设计] 的控制。您应该始终完全控制系统状态。

  3. 诸如运行的线程未停止之类的编程问题通常会隐藏起来。
  4. 您可能会遇到不一致的应用程序状态异常中断线程。(参考#3)

By the way: Returning other return codes than 0 does make sense if you want to indicate abnormal program termination.

顺便说一句:如果您想指示异常程序终止,返回 0 以外的其他返回代码确实有意义。

回答by John

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:

虽然答案真的很有帮助,但它是如何错过了更多额外细节的。除了上面的答案,我希望下面能帮助理解java中的关机过程:

  1. In an orderly* shutdown, the JVM first starts all registered shutdown hooks. Shutdown hooks are unstarted threads that are registered with Runtime.addShutdownHook.
  2. JVM makes no guarantees on the order in which shutdown hooks are started. If any application threads (daemon or nondaemon) are still running at shutdown time, they continue to run concurrently with the shutdown process.
  3. When all shutdown hooks have completed, the JVM may choose to run finalizers if runFinalizersOnExit is true, and then halts.
  4. JVM makes no attempt to stop or interrupt any application threads that are still running at shutdown time; they are abruptly terminated when the JVM eventually halts.
  5. If the shutdown hooks or finalizers don't complete, then the orderly shutdown process “hangs” and the JVM must be shut down abruptly.
  6. In an abrupt shutdown, the JVM is not required to do anything other than halt the JVM; shutdown hooks will not run.
  1. 在有序*关闭中,JVM 首先启动所有已注册的关闭挂钩。关闭钩子是使用 Runtime.addShutdownHook 注册的未启动线程。
  2. JVM 不保证关闭钩子的启动顺序。如果任何应用程序线程(守护进程或非守护进程)在关闭时仍在运行,它们将继续与关闭进程同时运行
  3. 当所有关闭挂钩都完成后,如果 runFinalizersOnExit 为真,JVM 可能会选择运行终结器,然后停止。
  4. JVM 不会尝试停止或中断在关闭时仍在运行的任何应用程序线程;当 JVM 最终停止时,它们会突然终止。
  5. 如果关闭钩子或终结器没有完成,那么有序关闭过程“挂起”,JVM 必须突然关闭。
  6. 在突然关闭时,除了停止 JVM 之外,JVM 不需要做任何事情;关闭挂钩将不会运行。

PS: The JVM can shut down in either an orderlyor abruptmanner.

PS:JVM 可以以有序突然的方式关闭。

  1. An orderly shutdown is initiated when the last “normal” (nondaemon) thread terminates, someone calls System.exit, or by other platform-specific means (such as sending a SIGINT or hitting Ctrl-C).
  2. While above is the standard and preferred way for the 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).
  1. 当最后一个“正常”(非守护进程)线程终止、有人调用 System.exit 或通过其他特定于平台的方式(例如发送 SIGINT 或按 Ctrl-C)时,将启动有序关闭。
  2. 虽然上面是JVM关闭的标准和首选方式,但也可以通过调用Runtime.halt或通过操作系统杀死JVM进程(例​​如发送SIGKILL)来突然关闭它。