What are the circumstances under which a finally {} block will NOT execute?

丶灬走出姿态 提交于 2019-11-27 07:05:48
Peter Lawrey

If you call System.exit() the program exits immediately without finally being called.

A JVM Crash e.g. Segmentation Fault, will also prevent finally being called. i.e. the JVM stops immediately at this point and produces a crash report.

An infinite loop would also prevent a finally being called.

The finally block is always called when a Throwable is thrown. Even if you call Thread.stop() which triggers a ThreadDeath to be thrown in the target thread. This can be caught (it's an Error) and the finally block will be called.


public static void main(String[] args) {
    testOutOfMemoryError();
    testThreadInterrupted();
    testThreadStop();
    testStackOverflow();
}

private static void testThreadStop() {
    try {
        try {
            final Thread thread = Thread.currentThread();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    thread.stop();
                }
            }).start();
            while(true)
                Thread.sleep(1000);
        } finally {
            System.out.print("finally called after ");
        }
    } catch (Throwable t) {
        System.out.println(t);
    }
}

private static void testThreadInterrupted() {
    try {
        try {
            final Thread thread = Thread.currentThread();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    thread.interrupt();
                }
            }).start();
            while(true)
                Thread.sleep(1000);
        } finally {
            System.out.print("finally called after ");
        }
    } catch (Throwable t) {
        System.out.println(t);
    }
}

private static void testOutOfMemoryError() {
    try {
        try {
            List<byte[]> bytes = new ArrayList<byte[]>();
            while(true)
                bytes.add(new byte[8*1024*1024]);
        } finally {
            System.out.print("finally called after ");
        }
    } catch (Throwable t) {
        System.out.println(t);
    }
}

private static void testStackOverflow() {
    try {
        try {
            testStackOverflow0();
        } finally {
            System.out.print("finally called after ");
        }
    } catch (Throwable t) {
        System.out.println(t);
    }
}

private static void testStackOverflow0() {
    testStackOverflow0();
}

prints

finally called after java.lang.OutOfMemoryError: Java heap space
finally called after java.lang.InterruptedException: sleep interrupted
finally called after java.lang.ThreadDeath
finally called after java.lang.StackOverflowError

Note: in each case the thread kept running, even after SO, OOME, Interrupted and Thread.stop()!

Infinite loop in the try block.

Corrupt RAM? Program no longer runs as written? I've actually debugged that once on a DOS machine.

There is a chance of partial execution when finally itself throws an exception (or leads to an error)

One could be "A finally is a part of daeomon thread it may not be executed".

The only times finally won't be called are:

if the power turns off

  1. if you call System.exit()
  2. if the JVM crashes first
  3. if there is an infinite loop in the try block
  4. if the power turns off

Testing the finally block in different statement in try block.

 public static void main(String [] args){

    try{
        System.out.println("Before Statement");
        /*** Statement ***/
        System.out.println("After Statement");
    }
    catch(Exception e){
    }
    finally{
        System.out.println("Finally is Executed");
    }

Statements in which finally block is executed are following:

  1. Thread.currentThread().interrupted();
  2. Thread.currentThread().destroy();
  3. Thread.currentThread().stop();
  4. Thread.sleep(10);
  5. Thread.currentThread().interrupt();
  6. Runtime.getRuntime().addShutdownHook(Thread.currentThread());
  7. If there is any exception occurred.
  8. If there is no exception.

Statements in which finally block is not executed are following:

  1. Thread.currentThread().suspend();
  2. System.exit(0);
  3. JVM crashed.
  4. Power to CPU chip goes off.
  5. OS kills JVM process.
  6. Runtime.getRuntime().exit(0);
  7. Runtime.getRuntime().halt(0);

I think when JVM exits suddenly due to any reason, that can be a cause the control will not enter into the the finally block and never execute.

Sambhav

You can make it a part of Daemon Thread. You may use the method setDaemon(boolean status) which is used to mark the current thread as daemon thread or user thread and exit the JVM as and when required. This will enable you exit the JVM before finally{} is executed.

Another possible instance of a finally block never executing would be due to a design where the method returned before the try block was entered, as in the cases of some very bad code I've seen from time to time:

public ObjectOfSomeType getMeAnObjectOfSomeType() throws SomeHorrendousException {
    if (checkSomeObjectState()) {
        return new ObjectOfSomeType();
    }

    try {
        // yada yada yada...
    } catch (SomeHorrendousException shexc) {
        // wow, do something about this horrendous exception...
    } finally {
        // do some really important cleanup and state invalidation stuff...
    }

I know none of you would ever do this, so I hesitated to add this as a possible scenario, but thought, eh, it's Friday, what the heck ; )

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!