Why Try-with-Resources Outperforms Try-Catch-Finally in Java
Java developers often close resources manually using try-catch-finally, but since JDK 7 the try‑with‑resources construct automates this process; this article explains the traditional pattern, demonstrates the new syntax, shows how to implement custom Closeable classes, and reveals the compiler‑generated bytecode that preserves original exceptions via addSuppressed.
Background
When a program opens resources such as files or streams, failing to close them on normal exit or when an exception occurs can lead to memory leaks. Historically Java developers used a try‑catch‑finally block to ensure resources were closed.
Traditional try‑catch‑finally
@Test
public void testOldProcess() {
Scanner scanner = null;
try {
scanner = new Scanner(new File("test.txt"));
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (scanner != null) {
scanner.close();
}
}
}The finally block guarantees that scanner.close() runs regardless of whether an exception was thrown.
JDK 7 try‑with‑resources
Since JDK 7 the language provides a concise syntax that automatically closes any resource that implements java.io.Closeable or java.lang.AutoCloseable:
@Test
public void testNewProcess() {
try (Scanner scanner = new Scanner(new File("test.txt"))) {
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}Multiple resources can be declared by separating them with semicolons:
@Test
public void testNewProcess1() {
try (
Scanner scanner = new Scanner(new File("test.txt"));
Scanner scanner1 = new Scanner(new File("test1.txt"))
) {
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
while (scanner1.hasNext()) {
System.out.println(scanner1.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}Only classes that implement Closeable can be used. Scanner already implements this interface.
Custom Closeable implementation
public class MyResource implements Closeable {
public void hello(){
System.out.println("Hello try-catch-resource");
}
@Override
public void close() throws IOException {
System.out.println("自定义的close方法被自动调用了...");
}
} @Test
public void testMyResource() {
try (MyResource resource = new MyResource()) {
resource.hello();
} catch (IOException exception) {
exception.printStackTrace();
}
}Running the test prints the hello message followed by the custom close message, showing that the JVM invoked close() automatically.
What the compiler generates
The Java compiler translates the try‑with‑resources construct into bytecode that uses a hidden try‑finally block and calls addSuppressed to preserve exceptions from the resource’s close() method.
public void testMyResource() {
try {
MyResource resource = new MyResource();
Throwable var2 = null;
try {
resource.hello();
} catch (Throwable var12) {
var2 = var12;
throw var12;
} finally {
if (resource != null) {
if (var2 != null) {
try {
resource.close();
} catch (Throwable var11) {
var2.addSuppressed(var11);
}
} else {
resource.close();
}
}
}
} catch (IOException var14) {
var14.printStackTrace();
}
}This shows that the construct is syntactic sugar; the compiler still generates a finally block, but it also records any exception thrown by close() as a suppressed exception.
Exception suppression in practice
When both the resource’s main method and its close() method throw exceptions, the traditional pattern hides the original exception:
public void testOldMyResource() {
MyResource resource = null;
try {
resource = new MyResource();
resource.hello(); // throws RuntimeException
} finally {
if (resource != null) {
resource.close(); // throws another RuntimeException, hides the first
}
}
}Output shows only the exception from close(), making debugging difficult.
With try‑with‑resources the original exception is retained and the exception from close() appears as a suppressed exception:
java.lang.RuntimeException: Resource throw Exception...
at com.secbro2.resource.MyResource.hello(MyResource.java:14)
...
Suppressed: java.lang.RuntimeException: Close method throw Exception...
at com.secbro2.resource.MyResource.close(MyResource.java:19)This behavior greatly simplifies bug tracing.
Conclusion
Try‑with‑resources, introduced in JDK 7, provides a cleaner way to manage resources compared with the manual try‑catch‑finally pattern. It relies on the Closeable contract, automatically generates the necessary cleanup code, and uses addSuppressed to avoid losing the original exception, making Java code both shorter and more reliable.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Senior Brother's Insights
A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
