Java có 4 mức độ reference strength (mạnh → yếu): Strong → Soft → Weak → Phantom. GC xử lý khác nhau tùy mức độ. java.lang.ref package cung cấp các wrapper.
1. SoftReference – Cache nhạy cảm bộ nhớ
- GC chỉ reclaim (thu hồi) soft-reachable objects khi JVM cần bộ nhớ (OOM imminent).
- Thích hợp cho memory-sensitive cache (image cache, parsed data cache).
- Có thể dùng với
ReferenceQueueđể cleanup sau khi GC clear.
Ví dụ SoftReference Cache
import java.lang.ref.SoftReference; import java.util.HashMap; import java.util.Map; public class SoftReferenceCache{ private final Map > cache = new HashMap<>(); public void put(K key, V value) { cache.put(key, new SoftReference<>(value)); } public V get(K key) { SoftReference ref = cache.get(key); if (ref == null) return null; V value = ref.get(); if (value == null) { cache.remove(key); // GC đã clear } return value; } public static void main(String[] args) { SoftReferenceCache cache = new SoftReferenceCache<>(); cache.put("key1", "Large data object 1"); cache.put("key2", "Large data object 2"); System.out.println("Before GC: " + cache.get("key1")); // Large data object 1 // Giả lập memory pressure System.gc(); // Chỉ hint, không guarantee try { Thread.sleep(100); } catch (InterruptedException e) {} System.out.println("After GC: " + cache.get("key1")); // Có thể null nếu GC reclaimed } }
2. WeakReference – Canonicalizing mappings, Observer pattern
- GC reclaim weak-reachable objects ở mọi GC cycle (không chờ memory pressure).
- Dùng cho
WeakHashMap(key weak), listener lists, canonicalizing maps.
Ví dụ WeakReference
import java.lang.ref.WeakReference;
public class WeakReferenceDemo {
public static void main(String[] args) {
Object obj = new Object() {
@Override public String toString() { return "MyObject"; }
};
WeakReference
3. PhantomReference – Pre-mortem cleanup, flexible finalization
- Phantom-reachable object: đã finalized (nếu có finalize), nhưng chưa bị reclaim.
phantomRef.get()luôn trả về null – không thể revive object.- BẮT BUỘC đăng ký với
ReferenceQueue– khi object phantom-reachable, reference được enqueue. - Dùng cho: cleanup native resources, off-heap memory, thay thế
finalize()(deprecated Java 9, removed Java 18).
Ví dụ PhantomReference (Sửa lỗi code gốc: get() trả null)
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class PhantomReferenceDemo {
public static void main(String[] args) {
ReferenceQueue
So sánh 4 loại Reference
| Reference Type | GC Reclaim Timing | get() trả về | ReferenceQueue | Use Case |
|---|---|---|---|---|
| Strong | Không bao giờ (trong khi reachable) | Object | Không | Normal object reference |
| Soft | Khi JVM cần memory (OOM imminent) | Object hoặc null | Optional | Memory-sensitive cache |
| Weak | Next GC cycle | Object hoặc null | Optional | WeakHashMap, listeners, canonicalizing |
| Phantom | Sau finalization, trước reclaim | Luôn null | Bắt buộc | Pre-mortem cleanup, native resource release |
Lưu ý quan trọng
finalize()deprecated (Java 9), removed (Java 18). DùngPhantomReference+ReferenceQueuehoặcCleaner(Java 9+).Cleanerlà high-level abstraction trên PhantomReference – dễ dùng hơn.- Reference objects bản thân cũng bị GC nếu không còn strong reference đến chúng.
Cleaner Example (Java 9+, khuyên dùng thay PhantomReference)
import java.lang.ref.Cleaner;
public class CleanerDemo {
private static final Cleaner cleaner = Cleaner.create();
static class Resource implements Runnable {
private final int id;
Resource(int id) { this.id = id; System.out.println("Resource " + id + " acquired"); }
public void run() { System.out.println("Cleaning up resource " + id); }
}
public static void main(String[] args) {
Resource res = new Resource(1);
// Đăng ký cleanup action
Cleaner.Cleanable cleanable = cleaner.register(res, res);
res = null; // Eligible for GC
System.gc();
// Cleanup action sẽ chạy khi GC reclaim object
}
}