在 Java 中,是否保证调用“finally”块(在 main 方法中)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/516049/
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-11 15:39:07  来源:igfitidea点击:

In Java, is the "finally" block guaranteed to be called (in the main method)?

javaerror-handlingfinally

提问by Hanno Fietz

I'm a Java rookie and I was wondering, if I have the following typical Java code

我是 Java 菜鸟,我想知道,如果我有以下典型的 Java 代码

public class MyApp {
  public static void main(String[] args) {
    try {
      // do stuff
    } catch {
      // handle errors
    } finally {
      // clean up connections etc.
    }
  }
}

does the JVM guarantee that the finally block will always be run? To understand where I'm coming from, I'm used to C/C++ programs that might just crash if you dereference a NULL pointer and you can't have any code to be run after that.

JVM 是否保证 finally 块将始终运行?为了理解我来自哪里,我习惯了 C/C++ 程序,如果您取消引用一个 NULL 指针,那么这些程序可能会崩溃,之后您无法运行任何代码。

But as I understand Java and the whole GC / managed memory business in general, there's no such thing as a null pointer dereferencing, everything is a catchable expection, so there's not really a way for my program to crash that could make it skip the finally, or is there? For example, in Python, I usually do

但正如我对 Java 和整个 GC/托管内存业务的一般理解,没有空指针取消引用这样的东西,一切都是一个可以捕捉的期望,所以我的程序实际上没有办法崩溃,可以让它跳过最后,或者有吗?例如,在Python中,我通常会这样做

try:
  # do stuff
except AnExceptionIKnewMightHappen:
  # react in an appropriate way
except:
  # log that weird error I had not known could happen

and I have never had any app die without passing through my code.

而且我从来没有在不通过我的代码的情况下死掉任何应用程序。

Of course, if the OS for some reason kills the process (or if something kills the whole system, like pulling the plug) there's not much Java can do. Also, from PHP I know non-catchable errors that you can't protect against, even though the interpreter was still there after it happened (at least it is able to output a proper message).

当然,如果操作系统出于某种原因杀死了进程(或者如果某些事情杀死了整个系统,比如拔掉插头),Java 就无能为力了。另外,从 PHP 我知道你无法防止的不可捕获的错误,即使解释器在它发生后仍然存在(至少它能够输出正确的消息)。

Edit:Just for clarity (it wasn't really misunderstood by anyone), let me add that I was looking for things inside my codethat could lead to the finally being bypassed. So pointing to System.exit was a helpful reminder, even though I can't see why I would want to do something like that.

编辑:为了清楚起见(任何人都没有真正误解),让我补充一点,我正在我的代码中寻找可能导致最终被绕过的东西。所以指向 System.exit 是一个有用的提醒,即使我不明白为什么我会想要做这样的事情。

The JVM exiting is a rather obvious way and I'd count that as an external cause. The note pointing out that you also have to remember the possibilty of threads exiting while the JVM and the app keep running was very helpful, because even though it also seems obvious to me now, I hadn't thought of it.

JVM 退出是一种相当明显的方式,我将其视为外部原因。指出您还必须记住当 JVM 和应用程序继续运行时线程退出的可能性非常有帮助,因为即使现在对我来说这也很明显,但我没有想到它。

采纳答案by Rob Grant

Basically yes, except for the note listed here(emphasis mine):

基本上是的,除了这里列出的注释(强调我的):

If the JVM exits while the try or catch code is being executed, then the finally block may notexecute. Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block may notexecute even though the application as a whole continues.

如果在执行 try 或 catch 代码时 JVM 退出,则 finally 块可能不会执行。同样,如果执行 try 或 catch 代码的线程被中断或终止,即使应用程序作为一个整体继续运行,finally 块也可能不会执行。

回答by Rob Grant

Erm, yep :) Whether your code enters a catch or not, the finally will run. It's a good place to put code that cleans up after the try.

嗯,是的 :) 无论您的代码是否输入 catch , finally 都会运行。这是放置尝试后清理的代码的好地方。

Obviously it won't run if you break the jvm :)

显然,如果你破坏了 jvm,它就不会运行:)

回答by Guillaume

Yes, the finally block will always be run, unless there is a crash of the JVM (very rare, but that can happen).

是的,finally 块将始终运行,除非 JVM 崩溃(非常罕见,但可能会发生)。

回答by cletus

It is not guaranteed:

不保证:

public class Main {
    public static void main(String args[]) {
        try {
            System.out.println("try");
            System.exit(0);
        } catch (Exception e) {
            System.out.println("exception");
        } finally {
            System.out.println("finally");
        }
    }
}

Run that.

运行那个。

回答by Martin McNulty

In a word, yes.

一句话,是的。

Code in the finally block in Java always executes unless:

Java 中 finally 块中的代码始终执行,除非:

  • The JVM exits during the try or catch block
  • The thread running the code is interrupted or killed during the try or catch block
  • JVM 在 try 或 catch 块期间退出
  • 运行代码的线程在 try 或 catch 块期间被中断或杀死

(from: http://java.sun.com/docs/books/tutorial/essential/exceptions/finally.html)

(来自:http: //java.sun.com/docs/books/tutorial/essential/exceptions/finally.html

So, unless you explicitly call System.exit(int), or kill the process or thread externally, you can rely on it.

因此,除非您显式调用 System.exit(int),或者在外部终止进程或线程,否则您可以依赖它。

回答by Arcane

Absolutely, that finally block will run, every time. Except in the case of a JVM crash or the exit() function being called. I have had code where the Java application made calls out to JNI native code which segfaulted. The resulting crash killed the JVM, and prevented the finally from running.

绝对的,finally 块每次都会运行。除非 JVM 崩溃或调用 exit() 函数。我有一些代码,其中 Java 应用程序调用了段错误的 JNI 本机代码。由此产生的崩溃杀死了 JVM,并阻止了 finally 运行。

回答by Johannes Weiss

Chris Cameron is correct. But normally a finally-block gets executed. Null pointer dereferece does exist in Java:

克里斯卡梅隆是对的。但通常finally会执行 -block。Java 中确实存在空指针取消引用:

try {
    List<Object> x = null;
    x.get(1); //throws the unchecked NullPointerException
} finally {
    //will be executed
}

The finally-Block gets executed.

finally-Block 被执行。

回答by paulmurray

Yes, the JVM always executes it. Gaurranteed.

是的,JVM 总是执行它。保证。

Of course ... if the JVM itselfdies (eg: System.exit()), then it's not in a position to gaurrantee anything. But the JVM dying is not a within-java issue.

当然……如果 JVM本身死掉(例如:System.exit()),那么它就无法保证任何事情。但是 JVM 的消亡并不是 Java 内部的问题。

回答by lwpro2

the only exceptions finally block is not executed are, either JVM crashes, or system.exit().

唯一不执行 finally 块的异常是 JVM 崩溃或 system.exit()。

回答by backslash

It seems pretty obvious that nothingmore will run after JVM quit, or will run code in that killed thread. Obvious. So, when the JVM is running, every code that will run, will run, and after a JVM quit or inside a dead thread , nothingwill run, even any kind of code. So, there is no way to prevent, but if there is a need to the finally clause, put it.

很明显,在 JVM 退出后不会再运行任何东西,或者会在被杀死的线程中运行代码。明显的。因此,当 JVM 运行时,每个将要运行的代码都会运行,并且在 JVM 退出或在死线程中之后,什么都不会运行,即使是任何类型的代码。所以,没有办法阻止,但是如果需要finally子句,就放它。