25

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

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

JVM 是否保证 finally 块将始终运行?为了理解我从哪里来,我已经习惯了 C/C++ 程序,如果你取消引用一个 NULL 指针并且你不能在此之后运行任何代码,这些程序可能会崩溃。

但据我了解 Java 和整个 GC / 托管内存业务一般来说,没有空指针解引用之类的东西,一切都是可捕获的预期,所以我的程序实际上没有办法崩溃,可以让它跳过 finally ,或者有吗?例如,在 Python 中,我通常会这样做

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

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

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

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

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

4

10 回答 10

47

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

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

于 2009-02-05T14:15:39.240 回答
13

不保证:

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");
        }
    }
}

运行那个。

于 2009-02-05T14:17:53.153 回答
10

一句话,是的。

Java 中 finally 块中的代码总是执行,除非:

  • JVM 在 try 或 catch 块期间退出
  • 运行代码的线程在 try 或 catch 块期间被中断或杀死

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

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

于 2009-02-05T14:17:56.303 回答
4

当然,finally 块每次都会运行。JVM 崩溃或调用 exit() 函数的情况除外。我有代码,Java 应用程序调用了出现段错误的 JNI 本机代码。由此产生的崩溃杀死了 JVM,并阻止了 finally 的运行。

于 2009-02-05T14:18:10.937 回答
2

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

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

finally-Block 被执行。

于 2009-02-05T14:20:38.607 回答
1

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

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

于 2009-02-06T05:21:49.973 回答
0

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

显然,如果您破坏 jvm,它将无法运行 :)

于 2009-02-05T14:15:23.237 回答
0

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

于 2009-02-05T14:15:44.873 回答
0

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

于 2010-11-01T03:35:41.973 回答
0

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

于 2017-03-02T00:05:17.320 回答