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

发布于 2024-09-19 13:21:46 字数 436 浏览 3 评论 0原文

在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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

花间憩 2024-09-26 13:21:46

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

"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 from main 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.

薯片软お妹 2024-09-26 13:21:46

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

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

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

要么抛出异常,要么虚拟机将终止返回之前。它永远不会“只是回来”。

很少有值得调用 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:

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.

陌路终见情 2024-09-26 13:21:46

该方法永远不会返回,因为这是世界末日,接下来不会执行任何代码。

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

System.exit(42);

谁将使用您的退出代码?调用应用程序的脚本。适用于 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

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.

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

本王不退位尔等都是臣 2024-09-26 13:21:46

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

吝吻 2024-09-26 13:21:46

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

我在我的代码中使用以下内容处理这个问题:

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

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. Calling System.exit will initiate the program's shutdown hooks and whatever thread that calls System.exit will block until program termination. This has the implication that if the shutdown hook in turn submits a task to the thread from which System.exit was called, the program will deadlock.

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();
}
泡沫很甜 2024-09-26 13:21:46

虽然答案确实很有帮助,但有些人错过了一些更多的额外细节。除了上面的答案之外,我希望下面的内容能够帮助理解java中的关闭过程:

  1. 在有序*关闭中,JVM首先启动所有已注册的关闭挂钩。关闭挂钩是使用 Runtime.addShutdownHook 注册的未启动线程。
  2. JVM 不保证关闭挂钩的顺序
    已开始。如果任何应用程序线程(守护程序或非守护程序)仍在运行
    在关闭时,它们继续与关闭过程同时运行
  3. 当所有关闭挂钩完成后,JVM 可能会选择运行终结器
    如果 runFinalizersOnExit 为 true,则停止。
  4. JVM 不会尝试停止或中断任何在关闭时仍在运行的应用程序线程;当 JVM 最终停止时,它们会突然终止。
  5. 如果关闭挂钩或终结器未完成,则有序关闭进程将“挂起”,并且 JVM 必须突然关闭。
  6. 在突然关闭时,JVM 除了停止 JVM 之外不需要执行任何操作; shutdown hooks 将不会运行。

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

  1. 当最后一个“正常”(非守护进程)线程终止、有人调用 System.exit 或通过其他特定于平台的方式(例如发送 SIGINT 或按 Ctrl-C)时,会启动有序关闭。
  2. 虽然以上是标准和首选方式
    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:

  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.

PS: The JVM can shut down in either an orderly or abrupt manner.

  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).
软糖 2024-09-26 13:21:46

由于以下原因,永远不要调用 System.exit(0)

  1. 它是一个隐藏的“goto”和“goto”,会破坏控制流。在这种情况下依赖钩子是团队中每个开发人员都必须了解的心理图。
  2. “正常”退出程序向操作系统提供与 System.exit(0) 相同的退出代码,因此它是多余的。

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

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

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

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

  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)

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

夜访吸血鬼 2024-09-26 13:21:46

需要 System.exit

  • 当您想返回非 0 错误代码时
  • 当您想从不是 main() 的地方退出程序时

在您的情况下,它与简单的 return-from-main 执行完全相同的操作。

System.exit is needed

  • when you want to return a non-0 error code
  • when you want to exit your program from somewhere that isn't main()

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

听风吹 2024-09-26 13:21:46

Java 语言规范

程序退出

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

所有非守护线程的线程都会终止。

某个线程调用类Runtime或类System的exit方法,
并且退出操作未被安全管理员禁止。

这意味着当您有大型程序(好吧,至少比这个更大)并且想要完成其执行时,您应该使用它。

Java Language Specification says that

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.

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.

韶华倾负 2024-09-26 13:21:46

如果您有另一个程序在 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?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文