当前位置:  开发笔记 > 编程语言 > 正文

finally块总是运行吗?

如何解决《finally块总是运行吗?》经验,为你挑选了8个好方法。

是否有任何条件最终可能无法在java中运行?谢谢.



1> hhafez..:

来自Sun教程

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

我不知道finally块不会执行的任何其他方式......


@dhiller - 我很确定"如果JVM退出......"中包含"断电":-p
@Jason Coco:终止(因为失去权力)与退出并不完全相同; 后者是一个或多或少有组织的过程,最终导致前者.,p
我想如果在finally块中抛出异常,则不会执行块的其余部分.

2> Eugene Yokot..:

System.exit关闭虚拟机.

终止当前运行的Java虚拟机.该参数用作状态代码; 按照惯例,非零状态代码表示异常终止.

此方法exit在类中调用该方法Runtime.此方法永远不会正常返回.

    try {
        System.out.println("hello");
        System.exit(0);
    }
    finally {
        System.out.println("bye");
    } // try-finally

"bye"不会在上面的代码中打印出来.


如果在执行System.exit(0)时发生异常,则finally块将执行.

3> 小智..:

只是为了扩展其他人所说的内容,任何不会导致JVM退出的事情都将导致finally块.所以方法如下:

public static int Stupid() {
  try {
    return 0;
  }
  finally {
    return 1;
  }
}

会奇怪地编译并返回1.


从finally块返回值被认为是个坏主意.要么仅从try块返回,要么从try/finally块外部返回.大多数IDE都会在警告时标记这一点.
@RanBiron当然.他实际上并没有建议在finally块中返回,他只是试图证明即使是一个return语句仍会导致所述块中的代码执行.
几个星期前,我真的很困惑了几个小时.
这很奇怪,在C#中不允许从finally块返回.

4> Zarkonnen..:

与System.exit相关,还存在某些类型的灾难性故障,其中finally块可能无法执行.如果JVM完全耗尽内存,它可能会在没有捕获或最终发生的情况下退出.

具体来说,我记得一个我们愚蠢地试图使用的项目

catch (OutOfMemoryError oome) {
    // do stuff
}

这不起作用,因为JVM没有剩余的内存来执行catch块.



5> Tom Hawtin -..:
try { for (;;); } finally { System.err.println("?"); }

在这种情况下,finally将不会执行(除非Thread.stop调用deprecated ,或者通过工具接口等效).



6> 小智..:

这个帖子中的Sun教程被错误地引用了.

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

如果你仔细研究sun教程中的finally块,它不会说"不会执行"但是"可能不会执行"这里是正确的描述

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

这种行为的明显原因是,在运行时系统线程中处理对system.exit()的调用,这可能需要一些时间来关闭jvm,同时线程调度程序可以最终要求执行.因此最终设计为始终执行,但如果您正在关闭jvm,可能会发生jvm在最终执行之前关闭.



7> wheleph..:

此外,如果在try块内发生死锁/活锁.

这是演示它的代码:

public class DeadLocker {
    private static class SampleRunnable implements Runnable {
        private String threadId;
        private Object lock1;
        private Object lock2;

        public SampleRunnable(String threadId, Object lock1, Object lock2) {
            super();
            this.threadId = threadId;
            this.lock1 = lock1;
            this.lock2 = lock2;
        }

        @Override
        public void run() {
            try {
                synchronized (lock1) {
                    System.out.println(threadId + " inside lock1");
                    Thread.sleep(1000);
                    synchronized (lock2) {
                        System.out.println(threadId + " inside lock2");
                    }
                }
            } catch (Exception e) {
            } finally {
                System.out.println("finally");
            }
        }

    }

    public static void main(String[] args) throws Exception {
        Object ob1 = new Object();
        Object ob2 = new Object();
        Thread t1 = new Thread(new SampleRunnable("t1", ob1, ob2));
        Thread t2 = new Thread(new SampleRunnable("t2", ob2, ob1));
        t1.start();
        t2.start();
    }
}

此代码生成以下输出:

t1 inside lock1
t2 inside lock1

并且"终于"永远不会被打印出来


从技术上讲,try块永远不会退出,所以finally块永远不会有机会执行.对于无限循环也可以这么说.

8> Mykhaylo Ada..:

以下是一些可以绕过finally块的条件:

    如果在执行try或catch代码时JVM退出,则finally块可能不会执行。

    正常关机-在最后一个非守护程序线程退出时或在Runtime.exit()时发生

    当线程退出时,JVM将对正在运行的线程进行清点,并且如果仅剩下的线程是守护程序线程,它将启动有序关闭。当JVM暂停时,所有剩余的守护程序线程都将被放弃,最后不执行块,堆栈也不会解开,只是退出JVM。应当尽可能少地使用守护程序线程,很少有处理活动可以在不清理的情况下随时安全地放弃。特别是,将守护程序线程用于可能执行任何I / O的任务是很危险的。最好将守护程序线程保存起来以用于“整理”任务,例如后台线程会定期从内存缓存中删除过期的条目。

最后一个非守护程序线程退出示例:

public class TestDaemon {
    private static Runnable runnable = new Runnable() {
        @Override
        public void run() {
            try {
                while (true) {
                    System.out.println("Is alive");
                    Thread.sleep(10);
                    // throw new RuntimeException();
                }
            } catch (Throwable t) {
                t.printStackTrace();
            } finally {
                System.out.println("This will never be executed.");
            }
        }
    };

    public static void main(String[] args) throws InterruptedException {
        Thread daemon = new Thread(runnable);
        daemon.setDaemon(true);
        daemon.start();
        Thread.sleep(100);
        // daemon.stop();
        System.out.println("Last non-daemon thread exits.");
    }
}

输出:

Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Last non-daemon thread exits.
Is alive
Is alive
Is alive
Is alive
Is alive

推荐阅读
k78283381
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有