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

*爱你&永不变心* 提交于 2019-11-26 13:02:39

问题


In a Java try{} ... catch{} ... finally{} block, code within the finally{} is generally considered \"guaranteed\" to run regardless of what occurs in the try/catch. However, I know of at least two circumstances under which it will not execute:

  • If System.exit(0) is called; or,
  • if an Exception is thrown all the way up to the JVM and the default behavior occurs (i.e., printStackTrace() and exit)

Are there any other program behaviors that will prevent the code in a finally{} block from executing? Under what specific conditions will the code execute or not?

EDIT: As NullUserException pointed out, the second case is actually not true. I thought it was because the text in standard error printed after that in standard out, preventing the text from being seen without scrolling up. :) Apologies.


回答1:


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()!




回答2:


Infinite loop in the try block.

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




回答3:


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




回答4:


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




回答5:


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



回答6:


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



回答7:


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.




回答8:


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.




回答9:


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



来源:https://stackoverflow.com/questions/12430642/what-are-the-circumstances-under-which-a-finally-block-will-not-execute

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