Does a finally block always run?

2019-01-02 17:27发布

Is there any condition where finally might not run in java? Thanks.

标签: java finally
12条回答
泪湿衣
2楼-- · 2019-01-02 17:46

Also if a deadlock/livelock happens inside try block.

Here's the code that demonstrates it:

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

This code produces the following output:

t1 inside lock1
t2 inside lock1

and "finally" never gets printed

查看更多
低头抚发
3楼-- · 2019-01-02 17:48
try { for (;;); } finally { System.err.println("?"); }

In that case the finally will not execute (unless the deprecated Thread.stop is called, or an equivalent, say, through a tools interface).

查看更多
人气声优
4楼-- · 2019-01-02 17:50
//If ArithmeticException Occur Inner finally would not be executed
class Temp
{
    public static void main(String[] s)
    {
        try
        {
        int x = 10/s.length;
        System.out.println(x);
        try
            {
                int z[] = new int[s.length];
                z[10] = 1000;
            }catch(ArrayIndexOutOfBoundsException e)
            {
                System.out.println(e);
            }
         finally
        {
            System.out.println("Inner finally");
        }
        }
        catch(ArithmeticException e)
        {
            System.out.println(e);
        }
    finally 
    {
        System.out.println("Outer Finally"); 
    }

System.out.println("Remaining Code");   
}
}
查看更多
流年柔荑漫光年
5楼-- · 2019-01-02 17:52

System.exit shuts down the Virtual Machine.

Terminates the currently running Java Virtual Machine. The argument serves as a status code; by convention, a nonzero status code indicates abnormal termination.

This method calls the exit method in class Runtime. This method never returns normally.

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

"bye" does not print out in above code.

查看更多
路过你的时光
6楼-- · 2019-01-02 17:56

Related to System.exit, there are also certain types of catastrophic failure where a finally block may not execute. If the JVM runs out of memory entirely, it may just exit without catch or finally happening.

Specifically, I remember a project where we foolishly tried to use

catch (OutOfMemoryError oome) {
    // do stuff
}

This didn't work because the JVM had no memory left for executing the catch block.

查看更多
公子世无双
7楼-- · 2019-01-02 17:58

Here are some conditions which can bypass a finally block:

  1. If the JVM exits while the try or catch code is being executed, then the finally block may not execute.
  2. Normal Shutdown - this occurs either when the last non-daemon thread exits OR when Runtime.exit()
  3. When a thread exits, the JVM performs an inventory of running threads, and if the only threads that are left are daemon threads, it initiates an orderly shutdown. When the JVM halts, any remaining daemon threads are abandoned finally blocks are not executed, stacks are not unwound the JVM just exits. Daemon threads should be used sparingly few processing activities can be safely abandoned at any time with no cleanup. In particular, it is dangerous to use daemon threads for tasks that might perform any sort of I/O. Daemon threads are best saved for "housekeeping" tasks, such as a background thread that periodically removes expired entries from an in-memory cache.

Last non-daemon thread exits example:

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

Output:

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
查看更多
登录 后发表回答