finally clause not always called?

937 views Asked by At

If the code below is run from an IDE or from the command line, and then stopped either:

  • Stopping its execution from eclipse (red button)
  • Pressing CTRL+C (command line)
  • Naturally (by replacing the while(true) loop by a for loop

never the finally clause is executed ("Finally" never printed out).

public class Test {
    public static void main(String[] args) {
        try {
            while (true) {
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("Finally");
        }
    }
}

Quoting the Java 7 specifications:

If execution of the try block completes normally, then the finally block is executed, and then there is a choice:

Any insights?

EDIT

Oops, my bad, a finite for loop cause the finally clause to be called. I haven't noticed the trace in my unit test. So their is no question now.

7

There are 7 answers

0
light_303 On

the execution never leaves the while loop. If you "red button" the execution it terminates the whole process - so no other code will be able to execute afterwards (unless it is a shutdown hook of the JVM)

3
Puce On
  • Stopping its execution from eclipse (red button)
  • Pressing CTRL+C (command line)

In these cases you terminate the JVM, so the try block does not complete "normally". No JVM, no interpretation of Java bytecode.

  • Naturally (by replacing the while(true) loop by a for loop

Not sure what is happening here. This should work if the for loop is terminable (not an endless-loop). Please post your code.

0
KDP On

Finally block will always be executed,except if you call system.exit() through program. This doesn't mean it will be called when you force stop your application which totally shuts down your jvm.

0
Marcos Vasconcelos On

By: Stopping its execution from eclipse (red button) Pressing CTRL+C (command line)

You are killing the proccess and nothing is executed after that.

And by replacing the while(true) loop by a for loop this would reach finally.

And the finally block is fired even with Exceptions.

    try{
        for(int i = 0; i < 10; i++);
        throw new RuntimeException("Ex");
    }catch(Throwable e){
        System.out.println("thrown");
    }finally{
        System.out.println("finally");
    }

This will print : thrown finally

Even not caughts exceptions will trigger finally

    try{
        throw new RuntimeException("Ex");
    }finally{
        System.out.println("finally");
    }

this prints finally then the application receive the RuntimeException.

Another way for killing the proccess entirely is by calling System.exit and it will not execute any code further (aka: other code and your finally)

    try{
        System.exit(0);
    }finally{
        System.out.println("finally");
    }

This prints nothing.

0
rfportilla On

Correct me if i am wrong, you are saying the finally block isn't getting run when you break out of the program? If so, then you are expecting the wrong behavior from the finally block. The finally will run as the code goes through it's normal course. For instance, when the try has completed (either successfully or with error). You are stopping the program, in which case, nothing else is going forward. The finally is meant to be a part of error handling. Stopping program is not error handling.

0
TheCodingFrog On

What you're doing is terminating the process before it's getting completed.

You can use shutdownhook to handle below scenario:

  • Because all of its threads have completed execution
  • Because of call to System.exit()
  • Because user hit CNTRL-C
  • System level shutdown or User Log-Off

e.g. below

package com.test;

public class Test {
    public static void main(String[] args) {

        Test test = new Test();
        test.attachShutDownHook();
        try {
            while (true) {
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("Finally");
        }
    }

    public void attachShutDownHook() {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.out.println("Inside Add Shutdown Hook");
            }
        });
        System.out.println("Shut Down Hook Attached.");
    }
}

Finally will get called only if there is exception or program terminates normally.

1
Raphael Amoedo On

It's an infinite loop. You should put a break point.

public class Test {
  public static void main(String[] args) {
    try {
        while (true) {
            Thread.sleep(1000);
            break; //Added
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        System.out.println("Finally");
    }
  }
}

Or you can use a flag to set when the loop should ends.

boolean myFlag = true;
while(myFlag) {
    doSomething();
    myFlag = false;
}