Introduction
Object destruction in Java is handled automatically by Garbage Collection (GC). The finalize() method was used for cleanup before garbage collection, but it’s deprecated since Java 9.
Garbage Collection
Automatic memory management - Java automatically destroys unused objects.
How it Works:
- Object created in heap memory
- When no references point to object
- Garbage collector marks it for collection
- Memory is freed
Example:
public class Main {
public static void main(String[] args) {
Student s1 = new Student("John"); // Object created
Student s2 = new Student("Alice"); // Object created
s1 = null; // Object "John" eligible for GC
s2 = null; // Object "Alice" eligible for GC
// Request garbage collection (not guaranteed)
System.gc();
}
}
class Student {
String name;
Student(String name) {
this.name = name;
}
}
When Object is Eligible for GC
1. Reference Set to null:
Student s = new Student("John");
s = null; // Object eligible for GC
2. Reference Reassigned:
Student s = new Student("John");
s = new Student("Alice"); // "John" object eligible for GC
3. Object Created Inside Method:
void method() {
Student s = new Student("John");
// After method ends, 's' is eligible for GC
}
4. Island of Isolation:
class Node {
Node next;
}
Node n1 = new Node();
Node n2 = new Node();
n1.next = n2;
n2.next = n1;
n1 = null;
n2 = null;
// Both objects eligible (isolated)
finalize() Method (Deprecated)
Called by garbage collector before destroying object.
Syntax:
protected void finalize() throws Throwable {
// Cleanup code
}
Example:
class Student {
String name;
Student(String name) {
this.name = name;
System.out.println(name + " created");
}
// finalize method (deprecated)
@Override
protected void finalize() throws Throwable {
System.out.println(name + " destroyed");
}
}
public class Main {
public static void main(String[] args) {
Student s1 = new Student("John");
Student s2 = new Student("Alice");
s1 = null;
s2 = null;
// Request GC
System.gc();
// Give time for GC
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Note: finalize() execution is not guaranteed.
Problems with finalize()
- Unpredictable: Don’t know when it will run
- Not Guaranteed: May never run
- Performance: Slows down GC
- Deprecated: Since Java 9
- Unreliable: Should not depend on it
Modern Alternatives
1. Try-with-Resources (Preferred):
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
// Use resource
} // Automatically closed
2. Explicit Cleanup Method:
class Database {
Connection conn;
void connect() {
// Connect to database
}
// Explicit cleanup
void close() {
if (conn != null) {
conn.close();
}
}
}
// Usage
Database db = new Database();
try {
db.connect();
// Use database
} finally {
db.close(); // Explicit cleanup
}
3. Cleaner API (Java 9+):
import java.lang.ref.Cleaner;
class Resource {
private static final Cleaner cleaner = Cleaner.create();
private final Cleaner.Cleanable cleanable;
Resource() {
this.cleanable = cleaner.register(this, new CleanupTask());
}
private static class CleanupTask implements Runnable {
@Override
public void run() {
// Cleanup code
System.out.println("Cleanup performed");
}
}
}
Requesting Garbage Collection
Methods:
// Method 1
System.gc();
// Method 2
Runtime.getRuntime().gc();
Important: These are requests, not commands. JVM may ignore.
Example:
class Demo {
int id;
Demo(int id) {
this.id = id;
System.out.println("Object " + id + " created");
}
@Override
protected void finalize() {
System.out.println("Object " + id + " finalized");
}
}
public class Main {
public static void main(String[] args) {
Demo d1 = new Demo(1);
Demo d2 = new Demo(2);
d1 = null;
d2 = null;
System.out.println("Requesting GC...");
System.gc();
System.out.println("End of main");
}
}
Memory Information
public class Main {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
System.out.println("Total Memory: " + runtime.totalMemory());
System.out.println("Free Memory: " + runtime.freeMemory());
System.out.println("Max Memory: " + runtime.maxMemory());
// Create many objects
for (int i = 0; i < 10000; i++) {
new String("Object " + i);
}
System.out.println("\nAfter creating objects:");
System.out.println("Free Memory: " + runtime.freeMemory());
// Request GC
System.gc();
System.out.println("\nAfter GC:");
System.out.println("Free Memory: " + runtime.freeMemory());
}
}
Best Practices
1. Don’t Use finalize():
// ✗ Bad (deprecated)
class Bad {
@Override
protected void finalize() {
// Cleanup
}
}
// ✓ Good (use try-with-resources)
class Good implements AutoCloseable {
@Override
public void close() {
// Cleanup
}
}
2. Explicit Cleanup:
class Resource {
void open() {
// Open resource
}
void close() {
// Close resource
}
}
// Usage
Resource r = new Resource();
try {
r.open();
// Use resource
} finally {
r.close();
}
3. AutoCloseable Interface:
class MyResource implements AutoCloseable {
void use() {
System.out.println("Using resource");
}
@Override
public void close() {
System.out.println("Resource closed");
}
}
// Usage with try-with-resources
try (MyResource resource = new MyResource()) {
resource.use();
} // Automatically closed
Complete Example
// Modern approach - AutoCloseable
class DatabaseConnection implements AutoCloseable {
private String connectionName;
DatabaseConnection(String name) {
this.connectionName = name;
System.out.println("Connection opened: " + name);
}
void executeQuery(String query) {
System.out.println("Executing: " + query);
}
@Override
public void close() {
System.out.println("Connection closed: " + connectionName);
}
}
public class Main {
public static void main(String[] args) {
// Try-with-resources ensures cleanup
try (DatabaseConnection conn = new DatabaseConnection("MyDB")) {
conn.executeQuery("SELECT * FROM users");
} // Automatically closed
System.out.println("Done");
}
}
Garbage Collection Types
Java has multiple GC algorithms:
- Serial GC: Single-threaded
- Parallel GC: Multi-threaded
- CMS (Concurrent Mark Sweep): Low pause
- G1 (Garbage First): Default in Java 9+
- ZGC: Ultra-low latency
Object Lifecycle
1. Created (new keyword)
↓
2. In Use (has references)
↓
3. Unreachable (no references)
↓
4. Eligible for GC
↓
5. finalize() called (if defined)
↓
6. Memory reclaimed
Quick Reference
// Make object eligible for GC
Student s = new Student();
s = null; // Eligible
// Request GC (not guaranteed)
System.gc();
Runtime.getRuntime().gc();
// finalize() (deprecated - don't use)
@Override
protected void finalize() throws Throwable {
// Cleanup code
}
// Modern approach - AutoCloseable
class Resource implements AutoCloseable {
public void close() {
// Cleanup
}
}
// Usage
try (Resource r = new Resource()) {
// Use resource
} // Auto-closed
Comparison
| Feature | finalize() | try-with-resources |
|---|---|---|
| Status | Deprecated | Recommended |
| Execution | Unpredictable | Guaranteed |
| When | Before GC | End of try block |
| Control | No control | Full control |
| Performance | Slower | Faster |
| Reliability | Unreliable | Reliable |
Exam Tips
Remember:
- Garbage Collection is automatic
- finalize() is deprecated (don’t use)
System.gc()is a request, not command- Object eligible when no references
- Use try-with-resources for cleanup
- Implement AutoCloseable interface
- Explicit cleanup methods better than finalize()
- finalize() not guaranteed to run
- finalize() runs before object destruction
- Modern approach: try-with-resources
Common Questions:
- What is garbage collection?
- What is finalize() method?
- When is object eligible for GC?
- How to request GC?
- Why is finalize() deprecated?
- What is alternative to finalize()?
- What is try-with-resources?
- How to implement AutoCloseable?