When working with files,network sockets,or database connections in Java, forgetting to close a resource is one of the most common causes of memory and file-descriptor leaks.
For years,developers relied on manual cleanup inside a finally block. While it works, it leads to bloated, nested code that is prone to subtle bugs.Here is why the old way is risky, and how Java's try-with-resources solves it cleanly.
The Clunky Way: Manual Cleanup in finally
In older Java code, closing a stream required nested try-catch blocks inside finally:
public static void riskyRead(String filename) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(filename));
System.out.println("Reading line: " + reader.readLine());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Why this is problematic:
- Verbose Boilerplate: Over half the function exists just to close a single stream safely.
-
Suppressed Exceptions: If an exception occurs in both the
tryblock and thefinallyblock, the exception infinallyoverwrites the original error, making debugging significantly harder.
The Modern Way: try-with-resources
Introduced in Java 7, try-with-resources automatically handles closing any resource that implements java.lang.AutoCloseable.
Here is the exact same logic written cleanly:
public static void safeRead(String filename) {
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
System.out.println("Safe reading line: " + reader.readLine());
} catch (IOException e) {
System.err.println("Failed to read file: " + e.getMessage());
}
}
What happens behind the scenes:
- The resource (
BufferedReader) is initialized inside parentheses directly aftertry. - As soon as execution leaves the block—whether normally or via an exception—the JVM automatically invokes
reader.close(). - If both the read operation and the auto-close fail, Java preserves the original exception and attaches the secondary error via suppressed exceptions.
Complete Runnable Example
Runnable companion code available on GitHub.
Whenever you deal with I/O streams, database connections, or network sockets, verify if the class implements AutoCloseable. If it does, always wrap it in try-with-resources to eliminate resource leaks and unneeded boilerplate.
Top comments (0)