try(ResourceType resource = new ResourceType()) {
// Use the resource
}Java Try-With-Resources: Automatic Resource Management via AutoCloseable
Direct Answer & Core Concept
When a Java program works with files, database connections, network streams, sockets, or other external resources, those resources usually need to be closed after use.
Java provides try-with-resources to make this process safer and easier. It automatically closes resources when the try block finishes, even when an exception occurs.
This feature works with classes that implement the AutoCloseable or Closeable interface.
Detailed Explanation & Mechanics
What Is Try-With-Resources in Java?
Try-with-resources is a special form of the try statement that allows you to declare resources directly inside the try statement.
Java automatically calls the resource's close() method when execution leaves the block.
Basic syntax
For example:
try(FileInputStream input = new FileInputStream("data.txt")) {
// Read the file
}You do not need to manually write:
input.close();Java handles the closing automatically.
Why Is Resource Management Important?
Resources such as files and database connections are not ordinary Java objects. They may use operating-system or external-system resources.
If they are not closed properly, an application can experience:
File descriptor leaks
Database connection leaks
Memory/resource exhaustion
Locked files
Network connection problems
Reduced application performance
For example, repeatedly opening database connections without closing them can eventually exhaust the available connection pool.
Try-with-resources helps prevent these problems.
Traditional Resource Management Before Try-With-Resources
Before Java 7, developers commonly used a finally block to close resources.
FileInputStream input = null;
try {
input = new FileInputStream("data.txt");
// Read data
} catch (IOException e) {
e.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}This works, but it creates a lot of repetitive code.
There are also multiple places where exceptions can occur.
Using Try-With-Resources
The same basic operation can be written much more simply:
try(FileInputStream input = new FileInputStream("data.txt")) {
// Read data
} catch (IOException e) {
e.printStackTrace();
}When the try block finishes, Java automatically closes input.
This makes the code shorter and reduces the chance of forgetting to close the resource.
How Try-With-Resources Works
Suppose we write:
try(FileInputStream input = new FileInputStream("data.txt")) {
// Use input
}Conceptually, Java ensures that:
input.close();is performed when the try block is exited.
This happens whether the block finishes normally or an exception is thrown.
The important idea is:
The resource is automatically closed when execution leaves the try-with-resources statement.
What Is AutoCloseable?
AutoCloseable is a Java interface that defines a close() method.
Its basic form is:
public interface AutoCloseable {
void close() throws Exception;
}A class implementing AutoCloseable can be used as a resource in try-with-resources.
Simple example
class MyResource implements AutoCloseable {
public void use() {
System.out.println("Using resource");
} @Override public void close() {
System.out.println("Resource closed");
}
}Now it can be used like this:
try(MyResource resource = new MyResource()) {
resource.use();
}Output:
Using resourceResource closedThe close() method is called automatically.
AutoCloseable vs Closeable
Java also provides the Closeable interface.
The relationship is:
AutoCloseable ↑ CloseableCloseable extends AutoCloseable.
For example:
public interface Closeable extends AutoCloseable {
void close() throws IOException;
}The main difference is the exception type declared by close().
AutoCloseable can declare:
throws Exceptionwhile Closeable uses:
throws IOExceptionMany I/O classes implement Closeable.
Simple Custom AutoCloseable Example
You can create your own resource class.
class DatabaseConnection implements AutoCloseable {
public void connect() {
System.out.println("Database connected");
} public void query() {
System.out.println("Executing query");
} @Override public void close() {
System.out.println("Database connection closed");
}
}Use it with try-with-resources:
public class Main {
public static void main(String[] args) {
try(DatabaseConnection db = new DatabaseConnection()) {
db.connect();
db.query();
}
}
}Output:
Database connectedExecuting queryDatabase connection closedTry-With-Resources and Exceptions
One of the biggest advantages of try-with-resources is that resources are closed even when an exception occurs.
try(MyResource resource = new MyResource()) {
System.out.println("Working...");
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Exception occurred");
}Even though the calculation causes an exception, Java still closes the resource.
The general flow is:
Create resource↓Enter try block↓Use resource↓Exception occurs↓Resource is closed↓Exception is handledMultiple Resources in Try-With-Resources
You can manage multiple resources in a single try statement.
try( FileInputStream input = new FileInputStream("input.txt");
FileOutputStream output = new FileOutputStream("output.txt")) {
// Copy data
} catch (IOException e) {
e.printStackTrace();
}Both resources are automatically closed.
Order of Closing Multiple Resources
When multiple resources are declared, Java closes them in the reverse order of their declaration.
For example:
try( ResourceA a = new ResourceA();
ResourceB b = new ResourceB();
ResourceC c = new ResourceC()) {
}The closing order is:
C.close()B.close()A.close()This is called LIFO — Last In, First Out.
This ordering is useful when one resource depends on another.
Example of Multiple Resource Closing
class Resource implements AutoCloseable {
private String name;
Resource(String name) {
this.name = name;
System.out.println(name + " opened");
} @Override public void close() {
System.out.println(name + " closed");
}
}Use it:
try( Resource first = new Resource("First");
Resource second = new Resource("Second");
Resource third = new Resource("Third")) {
System.out.println("Using resources");
}Output:
First openedSecond openedThird openedUsing resourcesThird closedSecond closedFirst closedSuppressed Exceptions in Try-With-Resources
Sometimes both the main operation and the close() method can throw exceptions.
For example:
class MyResource implements AutoCloseable {
@Override public void close() throws Exception {
throw new Exception("Close failed");
}
}And:
try(MyResource resource = new MyResource()) {
throw new Exception("Main operation failed");
} catch (Exception e) {
System.out.println(e.getMessage());
}The exception from the main try operation is the primary exception.
The exception generated while closing the resource becomes a suppressed exception.
You can inspect suppressed exceptions using:
e.getSuppressed();Example:
catch (Exception e) {
System.out.println("Main: " + e.getMessage());
for (Throwable suppressed : e.getSuppressed()) {
System.out.println("Suppressed: " + suppressed.getMessage());
}
}This mechanism prevents the resource-closing exception from hiding the original failure.
Java Try-With-Resources and Finally
Try-with-resources does not mean that finally no longer exists.
You can still use finally when additional cleanup or logic is required.
Example:
try(MyResource resource = new MyResource()) {
System.out.println("Working");
} finally {
System.out.println("Finally block executed");
}The resource is closed as part of the try-with-resources process.
The finally block can then be used for other cleanup logic if necessary.
Using an Existing Resource
Modern Java also allows an already-created resource to be used in try-with-resources if the variable is final or effectively final.
For example:
FileInputStream input = new FileInputStream("data.txt");
try(input) {
// Use input
} catch (IOException e) {
e.printStackTrace();
}Here, input is effectively final because it is not reassigned.
This feature was introduced in Java 9.
What Does Effectively Final Mean?
A variable is effectively final when it is assigned once and never reassigned.
This is valid:
FileInputStream input = new FileInputStream("data.txt");
try(input) {
// Use input
}But this would not work:
FileInputStream input = new FileInputStream("data.txt");
input = new FileInputStream("other.txt");
try(input) {
}Because input has been reassigned, it is not effectively final.
Try-With-Resources with BufferedReader
A common real-world example is reading a text file.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try(BufferedReader reader = new BufferedReader(new FileReader("data.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}The BufferedReader is automatically closed.
Because the reader wraps another resource, closing the outer reader also handles the underlying stream appropriately.
Try-With-Resources with Database Connections
Try-with-resources is especially useful with JDBC.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class Main {
public static void main(String[] args) {
String sql = "SELECT id, name FROM users";
try( Connection connection = DriverManager.getConnection( "jdbc:mysql://localhost/test", "root", "password");
PreparedStatement statement = connection.prepareStatement(sql);
ResultSet result = statement.executeQuery()) {
while (result.next()) {
System.out.println(result.getInt("id"));
System.out.println(result.getString("name"));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}The connection, statement, and result set are automatically closed.
This greatly reduces the risk of database resource leaks.
Try-With-Resources with InputStream
For binary files, you can use an input stream.
import java.io.FileInputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try(FileInputStream input = new FileInputStream("photo.jpg")) {
int data;
while ((data = input.read()) != -1) {
// Process byte
}
} catch (IOException e) {
e.printStackTrace();
}
}
}When the block finishes, input.close() is automatically called.
Try-With-Resources with OutputStream
You can also safely manage output streams.
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try(FileOutputStream output = new FileOutputStream("output.txt")) {
String message = "Hello Java";
output.write(message.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}The output stream is closed automatically.
Creating Your Own Resource Class
Any class can participate in try-with-resources by implementing AutoCloseable.
class FileProcessor implements AutoCloseable {
public FileProcessor() {
System.out.println("Processor started");
} public void process() {
System.out.println("Processing file...");
} @Override public void close() {
System.out.println("Processor stopped");
}
}Then:
public class Main {
public static void main(String[] args) {
try(FileProcessor processor = new FileProcessor()) {
processor.process();
}
}
}Output:
Processor startedProcessing file...Processor stoppedThis pattern is useful for custom resources such as:
API clients
Database wrappers
Lock managers
Temporary resources
Network connections
File processors
AutoCloseable with Checked Exceptions
An AutoCloseable implementation can declare a checked exception from close().
class MyResource implements AutoCloseable {
@Override public void close() throws Exception {
System.out.println("Closing resource");
}
}Therefore, the caller may need to handle or declare the exception.
try(MyResource resource = new MyResource()) {
System.out.println("Working");
} catch (Exception e) {
e.printStackTrace();
}AutoCloseable with Runtime Exceptions
A resource does not have to declare a checked exception.
class MyResource implements AutoCloseable {
@Override public void close() {
System.out.println("Closed");
}
}Then:
try(MyResource resource = new MyResource()) {
System.out.println("Working");
}No checked exception handling is required for close() in this example.
Can a Resource Be Null?
Yes.
A null resource does not cause Java to call close() on that resource.
For example:
MyResource resource = null;
try(resource) {
System.out.println("Inside try");
}The important point is that Java cannot call close() on a null reference.
Common Mistake: Manually Closing the Resource
One common mistake is unnecessarily closing a resource inside the try block.
For example:
try(FileInputStream input = new FileInputStream("data.txt")) {
// Use input
input.close();
}This is usually unnecessary.
The try-with-resources statement already manages the resource.
Prefer:
try(FileInputStream input = new FileInputStream("data.txt")) {
// Use input
}Common Mistake: Closing Only on the Success Path
Without try-with-resources, developers may accidentally close a resource only when the operation succeeds.
For example:
FileInputStream input = new FileInputStream("data.txt");
process(input);
input.close();If process() throws an exception, input.close() may never execute.
Try-with-resources avoids this problem:
try(FileInputStream input = new FileInputStream("data.txt")) {
process(input);
}The resource is closed when the try statement exits.
Common Mistake: Catching Everything Unnecessarily
You do not always need a large catch block.
For example:
try(MyResource resource = new MyResource()) {
resource.use();
} catch (Exception e) {
e.printStackTrace();
}In production applications, it is often better to catch specific exceptions and handle them appropriately.
For example:
try(MyResource resource = new MyResource()) {
resource.use();
} catch (IOException e) {
System.err.println("Unable to read resource.");
}The appropriate exception handling depends on the application.
Try-With-Resources vs Finally
| Feature | Try-With-Resources | Traditional finally |
|---|---|---|
| Automatic closing | Yes | No |
| Code size | Smaller | Usually larger |
| Exception safety | Strong | More manual |
| Multiple resources | Easy | More complex |
| Resource ordering | Automatic | Manual |
| Introduced | Java 7 | Older Java feature |
| Recommended for closeable resources | Yes | Mainly for other cleanup |
For resources implementing AutoCloseable, try-with-resources is generally the preferred approach.
Benefits of Try-With-Resources
1. Automatic Cleanup
Resources are closed automatically when the statement finishes.
2. Less Boilerplate
You do not need large finally blocks just to close resources.
3. Better Exception Safety
Resources are closed even when an exception interrupts normal execution.
4. Multiple Resource Support
Several resources can be managed in a single try statement.
5. Suppressed Exception Handling
Java preserves exceptions thrown during resource closing as suppressed exceptions.
6. Cleaner Code
The resource's lifetime is clearly visible directly in the try statement.
When Should You Use Try-With-Resources?
Use try-with-resources whenever you work with a resource that implements AutoCloseable or Closeable.
Typical examples include:
FileInputStreamFileOutputStreamBufferedReaderBufferedWriterInputStreamOutputStreamSocketDatabase ConnectionPreparedStatementResultSetScannerAlways check the API documentation for the specific resource and its ownership rules.
Best Practices
Prefer Try-With-Resources
For closeable resources, prefer:
try(Resource resource = createResource()) {
// Work
}instead of manually managing close() in finally.
Keep the Resource Scope Small
Open a resource as close as possible to where it is needed.
try(BufferedReader reader = openFile()) {
// Only file-related work
}A smaller scope makes resource ownership easier to understand.
Use Multiple Resources Carefully
If several resources depend on each other, declare them in the correct order so that reverse-order closing is appropriate.
Handle Exceptions Meaningfully
Do not simply ignore exceptions from resource operations.
catch (IOException e) {
logger.error("Unable to process file", e);
}Avoid Unnecessary Manual close()
If try-with-resources owns the resource, normally let it perform the closing.
Try-With-Resources vs Manual Close
Manual approach
Resource resource = null;
try {
resource = createResource();
resource.use();
} finally {
if (resource != null) {
resource.close();
}
}Modern approach
try(Resource resource = createResource()) {
resource.use();
}The second version is easier to read and less error-prone.
Real-World Example
Imagine a web application that processes uploaded files.
Without proper resource management:
Upload file↓Open file stream↓Process file↓Exception occurs↓Stream remains open↓Resources accumulateWith try-with-resources:
Upload file↓Open file stream↓try-with-resources↓Process file↓Success or exception↓Stream automatically closedThis makes resource cleanup much more reliable.
Important Interview Question: What Happens Internally?
Consider:
try(MyResource resource = new MyResource()) {
resource.use();
}Conceptually, Java guarantees that the resource is closed when control leaves the try block.
If an exception occurs during the main operation, Java attempts to close the resource before propagating the exception.
If close() also throws an exception, that closing exception is retained as a suppressed exception associated with the primary exception.
This is one of the major improvements over many manual cleanup patterns.
Java Try-With-Resources Syntax Cheat Sheet
One resource
try(Resource r = new Resource()) {
// Work
}Multiple resources
try( ResourceA a = new ResourceA();
ResourceB b = new ResourceB()) {
// Work
}With catch
try(Resource r = new Resource()) {
// Work
} catch (Exception e) {
// Handle exception
}With finally
try(Resource r = new Resource()) {
// Work
} finally {
// Additional cleanup
}Existing effectively-final resource
Resource r = new Resource();
try(r) {
// Work
}Frequently Asked Questions
What is try-with-resources in Java?
Try-with-resources is a Java feature that automatically closes resources after they are used. It works with objects implementing AutoCloseable or Closeable.
Which Java version introduced try-with-resources?
Try-with-resources was introduced in Java 7.
What is AutoCloseable?
AutoCloseable is an interface that defines a close() method. Classes implementing it can be automatically closed by try-with-resources.
What is the difference between AutoCloseable and Closeable?
Closeable extends AutoCloseable. Closeable is commonly used for I/O resources and declares IOException, while AutoCloseable allows a broader Exception declaration.
Does try-with-resources work when an exception occurs?
Yes. The resource is closed when the try-with-resources statement exits, including when an exception occurs.
Can try-with-resources handle multiple resources?
Yes. You can declare multiple resources in the same try statement.
In what order are multiple resources closed?
They are closed in reverse declaration order. The last resource declared is closed first.
What are suppressed exceptions?
If the main operation throws an exception and closing a resource also throws an exception, the closing exception can be stored as a suppressed exception.
Can I create my own AutoCloseable class?
Yes. Implement AutoCloseable and provide the required close() method.
Should I manually call close() inside try-with-resources?
Usually no. The purpose of try-with-resources is to manage the resource automatically.
Graphics and Design Ideas
Graphic 1: Try-With-Resources Lifecycle
Create a simple flow diagram:
Create Resource↓Try Block↓Use Resource↓Success / Exception↓Automatic close()Graphic 2: Multiple Resource Closing
Show:
Resource AResource BResource C↓C closes first↓B closes second↓A closes lastLabel it LIFO: Last In, First Out.
Graphic 3: AutoCloseable Relationship
Create a small hierarchy:
AutoCloseable ↑ Closeable ↑ File I/O ClassesGraphic 4: Manual vs Automatic Cleanup
Two-column visual:
Manual Cleanup Try-With-Resourcestry try(resource)↓↓use resource use resource↓↓finally automatic close↓close resourceThese graphics can make the page easier for beginners to understand and can also improve the visual quality of the tutorial page.
Runnable Code Example: Java Try-With-Resources
Java 17+import java.io.BufferedReader;
import java.io.StringReader;
import java.io.IOException;
public class TryWithResourcesDemo {
public static void main(String[] args) {
String sampleData = "Line 1: Header\nLine 2: Data Record";
// Automatically closed upon exiting try block
try(BufferedReader reader = new BufferedReader(new StringReader(sampleData))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println("Read: " + line);
}
} catch (IOException e) {
System.err.println("I/O error: " + e.getMessage());
}
}
}