What is the AutoCloseable interface?
AutoCloseable appeared in Java 7 specifically for try-with-resources. Closeable (Java 5) was only for I/O streams. AutoCloseable - in java.lang (no imports needed), so any resou...
Junior Level
Definition
java.lang.AutoCloseable is an interface with a single close() method that is called automatically on exit from a try-with-resources block.
AutoCloseable appeared in Java 7 specifically for try-with-resources. Closeable (Java 5) was only for I/O streams. AutoCloseable - in java.lang (no imports needed), so any resource can become “closeable”.
public interface AutoCloseable {
void close() throws Exception;
}
How to use
// FileInputStream implements AutoCloseable
try (FileInputStream fis = new FileInputStream("file.txt")) {
fis.read();
} // fis.close() is called automatically
Which classes implement it
InputStream/OutputStream- files, networkConnection/Statement- databaseReader/Writer- textScanner- utilities
Why it’s needed
So you don’t forget to close resources. Before Java 7, you had to write finally with close() manually.
Middle Level
Why in java.lang?
This is a fundamental interface. It was placed in java.lang so it’s available everywhere without imports - at the level of Runnable or Iterable.
Correct close() implementation
1. Narrowing exception type:
The interface declares throws Exception. Override with a more specific type:
public class MyResource implements AutoCloseable {
@Override
public void close() throws IOException { // more specific
// closing
}
}
Or no throws at all if the method is safe.
2. “Safe Close” pattern: If a resource owns several sub-resources:
public void close() throws Exception {
try {
subResource1.close();
} finally {
subResource2.close(); // will close even if first failed
}
}
3. Idempotency:
Repeated close() call should not throw an exception.
Garbage Collector and AutoCloseable
AutoCloseable does not replace memory management. A resource (file, socket) is a native OS descriptor. If you don’t call close(), the descriptor “hangs” until GC collects the object.
This leads to “Too many open files” error.
Three approaches to resource management
| Mechanism | When triggered | Guarantee | Recommendation |
|---|---|---|---|
| TWR | On block exit | Guaranteed | Primary method |
| Cleaner | When GC decides | Fallback | Fallback if forgot close() |
| finalize() | When GC decides | Unpredictable | Deprecated (Java 9) |
Senior Level
Under the Hood: native descriptors
A resource is not a Java object, but an OS descriptor. A descriptor is a number (int) that the OS issues when opening a file/socket. Java object is just a wrapper. GC sees the wrapper but not the native resource in OS. Without explicit close(), the descriptor leaks even if GC collected the Java object. GC doesn’t see native resources. Without close() descriptor leaks even if Java object is collected.
Atomic State in multithreaded environments
public class MyResource implements AutoCloseable {
private final AtomicBoolean closed = new AtomicBoolean(false);
public void close() {
if (closed.compareAndSet(false, true)) {
// actual resource release
}
}
}
Two threads must not close one socket simultaneously - undefined behavior at the native driver level.
Throwing exceptions in constructor
If constructor threw an exception after opening a native resource but before returning the object - leak:
public class MyResource implements AutoCloseable {
private final NativeHandle handle;
public MyResource(String path) {
this.handle = openNative(path); // opened
if (!validate(path)) {
throw new IllegalArgumentException(); // handle leaked!
}
}
}
Solution: light constructors, heavy opening - under try-with-resources.
Cleaner instead of Finalizer (Java 9+)
finalize() is deprecated. For resource “insurance” use java.lang.ref.Cleaner:
public class MyResource implements AutoCloseable {
private static final Cleaner cleaner = Cleaner.create();
private final Cleaner.Cleanable cleanable;
public MyResource() {
this.cleanable = cleaner.register(this, () -> {
// last line of defense - if close() was not called
System.err.println("Resource not closed properly!");
});
}
public void close() {
cleanable.clean();
}
}
// Cleaner is triggered by GC. When there are no more strong references to MyResource,
// GC marks the object for cleanup. Cleaner executes the lambda in a separate thread.
// This is NOT a replacement for TWR - GC may take minutes or even hours.
// Cleaner is insurance if you forgot close().
This is only insurance, not replacing the importance of TWR.
Diagnostics
- SonarLint Rule - “Resources should be closed”. Checks type hierarchy.
jcmd VM.native_memory- native memory monitoring- Descriptor leak - a common cause of JVM crash after days of operation
Interview Cheat Sheet
Must know:
AutoCloseableappeared in Java 7 specifically for try-with-resources- Single method:
void close() throws Exception - Located in
java.lang- available without imports, likeRunnable close()must be idempotent (repeated call is safe)- GC doesn’t see native descriptors - without
close()leak even if object collected - Narrow
throws Exceptionto specific type or remove entirely Cleaner(Java 9+) - insurance, but NOT a TWR replacement
Frequent follow-up questions:
- Why in java.lang, not java.io? - So any class can become closeable without imports, at the
Objectlevel - What happens if you don’t close a resource? - Native descriptor leak -> “Too many open files” -> JVM crash
- Can close() throw an exception? - Yes, that’s why in multi-resource TWR exceptions are suppressed
- How is Cleaner better than finalize()? - Cleaner is more predictable,
finalize()deprecated in Java 9
Red flags (NOT to say):
- “GC closes resources itself” - GC collects Java object, but not native descriptor
- “AutoCloseable only for I/O” - That’s
Closeable;AutoCloseablefor any resources - “close() doesn’t need to be idempotent” - Javadoc strongly recommends it, repeated call must not fail
Related topics:
- [[12. What is the difference between AutoCloseable and Closeable]]
- [[9. What is try-with-resources]]
- [[10. What are the requirements for resources in try-with-resources]]
- [[18. What is exception wrapping (wrapping)]]
- [[22. What happens if an exception also occurs in the finally block]]