When Does Java’s finally Block Actually Run? Surprising Edge Cases Explained

This article explores the execution rules of Java's finally block, showing when it may be skipped, how it interacts with return statements, and how return values are affected, illustrated with multiple code examples and detailed analysis.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
When Does Java’s finally Block Actually Run? Surprising Edge Cases Explained

Introduction

During a recent interview, a question about the behavior of the finally block revealed some gaps in my understanding, prompting a deeper investigation into when finally executes and what value it returns.

Does finally Always Execute?

Short answer: no . There are two situations where it does not run:

1. Return before entering the try block

public class TryCatchTest {
    private static int total() {
        int i = 11;
        if (i == 11) {
            return i; // return before try
        }
        try {
            System.out.println("执行try");
        } finally {
            System.out.println("执行finally");
        }
        return 0;
    }
    public static void main(String[] args) {
        System.out.println("执行main:" + total());
    }
}

Output:

执行main:11

2. Exception thrown before the try block

public class TryCatchTest {
    private static int total() {
        return 1 / 0; // exception before try
        try {
            System.out.println("执行try");
        } finally {
            System.out.println("执行finally");
        }
        return 0;
    }
    public static void main(String[] args) {
        System.out.println("执行main:" + total());
    }
}

Conclusion: if the program never reaches the try block, the finally block is not executed.

However, if the try block is entered, the finally block usually runs, except in extreme cases such as calling System.exit(0) inside the try block, which terminates the JVM before finally can execute.

When Exactly Does finally Run?

In a normal flow, finally executes before the return of the try block:

public class TryCatchTest {
    private static int total() {
        try {
            System.out.println("执行try");
            return 11;
        } finally {
            System.out.println("执行finally");
        }
    }
    public static void main(String[] args) {
        System.out.println("执行main:" + total());
    }
}

Output:

执行try
执行finally
执行main:11

Similarly, when an exception is thrown and caught, finally runs before the return in the catch block.

Return Values Inside finally

1. finally Without Its Own Return

public class TryCatchTest {
    private static int total() {
        int i = 0;
        try {
            System.out.println("执行try:" + i);
            return i;
        } finally {
            ++i;
            System.out.println("执行finally:" + i);
        }
    }
    public static void main(String[] args) {
        System.out.println("执行main:" + total());
    }
}

Output:

执行try:0
执行finally:1
执行main:0

Java saves the return value from the try block before executing finally. If finally does not contain its own return, the saved value is returned.

2. finally With Its Own Return

Example 1:

public class TryCatchTest {
    private static int total() {
        try {
            System.out.println("执行try");
            return 1;
        } finally {
            System.out.println("执行finally");
            return 2;
        }
    }
    public static void main(String[] args) {
        System.out.println("执行main:" + total());
    }
}

Output:

执行try
执行finally
执行main:2

When finally contains a return, that value overrides any previously saved return value.

Example 2 and 3 further demonstrate that the method’s final return value is determined by the return statements that actually execute, whether they are in try, catch, or finally.

Summary

The finally block is designed to run in most normal execution paths, ensuring cleanup code is executed. It runs before a return in the try or catch block, unless the JVM exits abruptly. If finally itself returns a value, that value becomes the method’s result; otherwise, the value saved earlier is returned.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaException HandlingCode examplesfinallytry/catchreturn
Java Architect Essentials
Written by

Java Architect Essentials

Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.