【问题标题】:Will a java exception terminate the whole java application?java异常会终止整个java应用程序吗?
【发布时间】:2013-09-07 14:39:19
【问题描述】:

我曾经认为当异常发生时,整个java应用程序都会被终止。比如我写了一个测试函数来测试我的想法。

public void test(){
    File fileDir=new File(sourceDataDir);
    if(fileDir.exists()){
        File[] files = fileDir.listFiles();
        for(int index=0 ; index<files.length ; index++){
            System.out.println("index = "+index);
            File file = files[index];
            if(index == 1)//delete a file to cause a FileNotFoundException
                file.delete();
            try {
                BufferedReader in = new BufferedReader(new FileReader(file));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
}

我手动删除了一个文件导致FileNotFoundException。我曾经认为当异常发生时整个应用程序将终止。但实际上,应用程序会继续读取剩余的文件。那么,我的问题是,在什么情况下异常会导致整个应用程序被终止?

【问题讨论】:

    标签: java multithreading exception exception-handling jvm


    【解决方案1】:

    我的问题是,在什么情况下,异常会导致整个应用程序被终止?

    永远不会。只有 System.exit() 会导致整个程序终止(和 JVM 崩溃)

    想想一个异常,就像一个强大的break;,它可以打破方法。中断可能导致循环退出,如果最后一个循环在唯一的非守护线程中,则程序将退出。但它不会导致它,即使它可能是你在程序死亡之前看到的最后一件事。

    【讨论】:

    • 彼得你能检查我提供的答案吗?我投了反对票,但我不知道为什么。
    • 好的,非常感谢您花时间参与其中。我会考虑到这一点。 +1也可以回答。我想我想提出同样的建议。
    【解决方案2】:

    如果catch 没有捕获到异常,将终止发生异常的线程。如果没有非守护线程保留,JVM 将终止。这是异常终止 JVM 的唯一方法。如果你捕捉到一个异常,它永远不会导致 JVM 终止。

    【讨论】:

    • 这是否意味着拥有一个捕获基本 Exception 类型(即 (catch (Exception e)){ })的 catch-all 块是一种好习惯,这样我们就可以确保没有 JVM 终止。
    • @AsifKamranMalick 需要了解在捕获异常后如何继续。否则,仅仅终止已经是最干净的解决方案。请注意,您可以install a handler for uncaught exceptions 处理它们,而无需在代码中添加try-catch 块,这对于实现全局策略更为可取。
    【解决方案3】:

    有两种主要类型的异常:

    • 不是运行时异常

    表示系统运行正常。您必须捕获异常,否则它将无法编译。 它永远不会终止应用程序。如果你想终止,你必须在 catch 块中调用 System.exit(ERROR_NUMBER) 或抛出运行时异常。

    • 运行时异常

    表示系统错误(例如,应用程序服务器配置错误)。你不必抓住它。 如果您没有捕获它,它会终止应用程序,或者如果您编写 J2EE 应用程序,AS 可能会处理它并继续您的应用程序。

    【讨论】:

    • 其实我只是测试了一下,RuntimeException 并没有终止。相反,它会将异常冒泡给更高级别的调用者(只要您没有将其吞没)
    • 我认为如果没有更高级别的调用者捕获它,该进程将终止(例如 NullPointerException)。应用服务器会吞下这些,因此企业应用程序错误不会导致整个 JavaEE 服务器崩溃。
    • @Gadam 你是如何测试它的?独立的 Java 进程或应用程序容器(例如 Tomcat)?
    【解决方案4】:

    所以,我的问题是,在什么情况下,异常会导致 整个应用程序被终止?

    有关异常的详细信息,请参阅docs。至于您的问题 FileNotFoundException 是一个已检查的异常,这意味着您需要处理它。现在你必须选择

    1. 捕获 FileNotFoundException 并处理(您可以简单地打印堆栈跟踪并继续)
    2. 或者你可以把它扔给父母(调用方法)

    在情况 1 中,您的 java 进程将一直持续到结束(假设没有发生运行时异常/错误)。

    在情况 2 中,如果您即使在父级(调用函数)中也没有捕获 FileNotFoundException 并且只是再次抛出它并继续这样做,则异常最终将落在 main() 方法中。如果你的 main() 方法抛出了这个异常,JVM 就会简单地关闭。

    澄清您的 cmets 的更新:

    捕获异常与是否捕获异常无关。如果出现未缓存的异常,您仍然可以捕获它并让程序继续进行。但不建议这样做,因为根据未缓存异常的定义(根本不应该发生),如果发生未缓存异常,您不应该恢复。

    考虑以下简单示例

    public static void main(String args[]) {
        try {
            String s = null;
            System.out.println(s.length());
        } catch (Exception e) {
            System.out.println("Catch runtime exception but not quite sure what to do with it");
        }
    
        System.out.println("Reached here even after uncatched Exception");
    }
    

    输出是

    Catch runtime exception but not quite sure what to do with it
    Reached here even after uncatched Exception
    

    所以基本上每当发生异常时,如果你没有从源点的任何级别捕获它,它最终会传播到 main() 并且 JVM 最终会关闭。如果您确实捕获了它(无论捕获或未捕获的异常),您的程序将继续(在未捕获的异常的情况下输出可能与预期不同)并终止。

    【讨论】:

    • 所以,只有未经检查的异常才可能导致main函数终止,对吧?如果是未经检查的异常,捕捉与否就变得毫无意义,所以,JVM并没有强制我们捕捉或抛出这个异常明确的,对吧?
    • 未经检查的异常通常是编程错误,如果正确实施(索引越界、空指针、类强制转换等)根本不会发生,因此调用者/用户通常不能做任何事情关于他们。即使检查了 Exception 并且我们只是在每个方法中抛出它,它最终会传播到 main 方法并且 JVM 将关闭。
    • “所以,只有未经检查的异常可能会导致主函数终止,对吧?” Uncatched 异常会导致线程终止。乍一看,除了 RuntimeException 或 Error 之外的异常似乎是不可能的,因为编译器会强制捕获已检查的异常,但有一些方法可以产生它们。例如。已弃用的方法 Thread.stop(Throwable) 允许抛出任意未声明的 throwable。您还可以更改方法以在编译调用者之后 声明检查异常。还有一些其他极端情况。
    【解决方案5】:

    这里是例外处理。它们有两种类型:CheckedUnchecked

    Checked 异常(不是RuntimeException 的子类的所有异常)必须在try-catch 中处理,否则代码将无法编译,就像在FileNotFoundException 的OP 问题中一样。正是由于这种强制处理,这些异常通常不会终止应用程序,除非它们一直被抛出到调用方法直到 main() 方法,在那里它们会停止它们所在的线程发生了。

    Unchecked 异常(所有属于 RuntimeException 子类的异常)不需要处理,因为它们来自编程/数据缺陷(考虑除以零异常或尝试访问空对象的成员等) .这些通常会破坏应用程序并使它们出现的线程崩溃,这可能是您的程序在单线程执行中。

    【讨论】:

      【解决方案6】:

      没有。 Exception handlers的java处理程序异常执行

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-23
        • 2017-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多