Showing posts with label Finally. Show all posts
Showing posts with label Finally. Show all posts

Sunday, 29 July 2012

Is Finally Always Called in a Try Catch Java Statement?

The short answer is no if System.exit() is called within a try statement (see here for more details).

Otherwise, as mentioned in the Javadoc, the finally statement is always executed even if return, continue, or break are called within try or catch. We can check this with the following code example:
public class TryCatchFinally {

    public static void main(String[] args) {
        print("Before Check");
        check();
        print("After Check");
    }

    public static void check() {
        for (int i=0;i<3;i++) {
            String round = "Round " + (i+1) + " ";
            print(round + "before try");
            try {
                if ( (i%3) == 0 ) {
                    print(round + "before break");
                    break;
                } else if ( (i%3) == 1 ) {
                    print(round + "before continue");
                    continue;
                } else { // (i%3) == 2
                    print(round + "before return");
                    return;
                }
            } catch(Throwable t) {
                print(round + "Caught throwable:\n" + t);
            } finally {
                print(round + "in finally");
            }
            print(round + "after try statement");
        }
        print("After for statement");
    }

    public static void print(String s) {
        System.out.println(s);
    }

}

Testing break in try statement

If we run the above program as is, we get:

Before Check
Round 1 before try
Round 1 before break
Round 1 in finally
After for statement
After Check

We can conclude the following:
  • Even though break is performed, the finally statement is called.
  • Statements after try and the for loop are not executed.
  • The check() method returns properly.

Testing continue in try statement

If we comment the break and return statement (and corresponding print), and run the program again, we get:

Before Check
Round 1 before try
Round 1 in finally
Round 1 after try statement
Round 2 before try
Round 2 before continue
Round 2 in finally
Round 3 before try
Round 3 in finally
Round 3 after try statement
After for statement
After Check

We can conclude the following:
  • Even though continue is performed, the finally statement is called.
  • The statement after try is not executed for continue.
  • The for loop post statement is executed.
  • The check() method returns properly.

Testing return in try statement

If we comment the break and continue statement (and corresponding print), and run the program again, we get:

Before Check
Round 1 before try
Round 1 in finally
Round 1 after try statement
Round 2 before try
Round 2 in finally
Round 2 after try statement
Round 3 before try
Round 3 before return
Round 3 in finally
After Check

We can conclude the following:
  • Even though return is invoked, the finally statement is called.
  • Statements after try and the for loop are not executed.
  • The check() method returns properly.

Conclusion

  • If return, continue, or break are invoked in try, it does not prevent finally from being executed.
  • In all cases, if the try statement belongs to a called method, this method returns properly.

Saturday, 28 July 2012

About Using System.Exit() in Try Catch Finally Java Statements

This post is an attempt at summarizing issues around using the Java system.exit() statements inside try {...} catch (...) {...} finally {...} statements.

We will use the following piece of code:
public class TryCatchFinallySystemExit {

  public static void main(String[] args) {

    System.setSecurityManager(new SecurityManager() {

      @Override
      public void checkPermission(Permission perm) { }

      @Override
      public void checkExit(int status) {
        // throw new SecurityException();
      }

    });

    System.out.println("Before Check");
    check();
    System.out.println("After Check");

  }

  public static void check() {

    try {

      System.out.println("Before System.exit(-1)");
      System.exit(-1);
      System.out.println("After System.exit(-1)");

    } catch(Throwable t) {

      System.out.println("Before System.exit(-2)");
      System.exit(-2);
      System.out.println("After System.exit(-2)");

    } finally {

      System.out.println("Before System.exit(-3)");
      System.exit(-3);
      System.out.println("After System.exit(-3)");

    }

    System.out.println("After try statement");

  }

}

The main method implements a SecurityManager, then calls the check() method. If we run this application as is, the output is the following:

Before Check
Before System.exit(-1)

We can conclude that:
  • System.exit(-1) is the last statement excuted.
  • Catch and Finally statements are not called.
  • The check() method does not return.

If we uncomment the throw new SecurityException(); and execute the application again, we get:

Before Check
Before System.exit(-1)
Before System.exit(-2)
Before System.exit(-3)

We can conclude that:
  • The SecurityException get the catch and finally statements to be executed.
  • Statements after System.exit() statements are not executed.
  • The check() method does not return.

For return, continue and break statements in try statements, see this post.

Disclaimer: this post contains information from personal notes and information available on StackOverflow.com.