Backend

99 Ngày Java — Ngày 76: Soft, Weak và Phantom Reference

SSite Admin
10 tháng 10, 2026 2 phút đọc 6 lượt xem
99 Ngày Java — Ngày 76: Soft, Weak và Phantom Reference

Biến trỏ tới đối tượng không phải lúc nào cũng giữ đối tượng sống mãi. Java có strong, soft, weak và phantom reference để biểu đạt các mức reachability. Chúng hữu ích khi làm cấu trúc phụ trợ hoặc theo dõi vòng đời đối tượng, nhưng không thay thế chính sách cache rõ ràng.

Soft, Weak và Phantom Reference

1. Strong và soft: giữ chắc hay nhường khi thiếu bộ nhớ

Tham chiếu thường là strong: chừng nào còn đường đi từ GC root, đối tượng chưa được thu gom. SoftReference chỉ giữ đối tượng khi JVM còn muốn giữ; GC có thể xóa nó theo nhu cầu bộ nhớ. Thời điểm xóa không phải hợp đồng về TTL hay dung lượng, vì thế cache production nên đặt giới hạn theo số phần tử hoặc trọng lượng.

byte[] value = new byte[1024];
var soft = new java.lang.ref.SoftReference<>(value);
value = null; // now only the soft reference may retain it
byte[] maybe = soft.get(); // may be null

2. WeakReference và WeakHashMap

Nếu đối tượng chỉ còn weak reference, GC có thể thu nó ở lần quét kế tiếp. WeakHashMap giữ key bằng weak reference; khi key không còn được giữ mạnh ở nơi khác, entry có thể biến mất. Nhưng value giữ ngược key sẽ tạo đường strong qua map và phá mục tiêu. Đừng dựa vào thời điểm entry biến mất để viết logic nghiệp vụ.

var metadata = new java.util.WeakHashMap<Object, String>();
Object key = new Object();
metadata.put(key, "debug-only");
key = null; // entry becomes eligible for removal; no timing promise

3. PhantomReference và ReferenceQueue

PhantomReference.get() luôn trả null; nó không dùng để lấy lại đối tượng. Kết hợp với ReferenceQueue, nó báo khi đối tượng đã đạt trạng thái có thể dọn dẹp; ứng dụng vẫn phải giữ chính đối tượng PhantomReference để nhận thông báo. Với tài nguyên ngoài heap, ưu tiên AutoCloseable và try-with-resources; Cleaner chỉ là đường dự phòng, không bảo đảm chạy đúng lúc.

var queue = new java.lang.ref.ReferenceQueue<Object>();
Object target = new Object();
var phantom = new java.lang.ref.PhantomReference<>(target, queue);
target = null;
// Later: queue.remove() can yield phantom; phantom.get() is always null.

4. Chọn công cụ theo hợp đồng

Strong cho dữ liệu phải tồn tại; weak cho metadata đi theo vòng đời key; phantom cho tín hiệu dọn dẹp cuối vòng đời. Soft chỉ là một gợi ý cho GC, không phải bộ nhớ đệm có kiểm soát. Dù chọn loại nào, hãy kiểm tra null sau get(), đo cache hit và dùng heap dump nếu nghi key hoặc value bị giữ ngoài ý muốn.

  • Cache cần giới hạn rõ và chính sách loại bỏ; không phó mặc cho GC.

  • Tài nguyên phải đóng chủ động bằng try-with-resources.

Mức tham chiếu là hợp đồng reachability, không phải lịch GC. Ngày 77 xem một nơi khác JVM chia sẻ chuỗi: String pool và intern().

Tài liệu đối chiếu

  • https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/ref/package-summary.html

  • https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/WeakHashMap.html

S

Site Admin

Engineer and writer. Building things with TypeScript and distributed systems.

Bình luận (0)

Bạn cần đăng nhập bằng Google để bình luận.

Hãy là người bình luận đầu tiên.

Bài viết liên quan

99 Ngày Spring — Ngày 76: Circuit Breaker với Resilience4j

CLOSED, OPEN, HALF_OPEN, fallback, bulkhead và rate limiter để giới hạn lỗi dây chuyền.

10 thg 10, 20262 phút5
K

Học System Design qua 21 bài: yêu cầu, capacity, database, cache, hệ phân tán và 6 bài thực hành, kèm bài tập, sơ đồ luồng và mục lục đầy đủ.

10 thg 10, 20266 phút3
S

Học cách đi từ vấn đề đến kiến trúc, phân biệt architecture với design và bảo vệ lựa chọn bằng yêu cầu, số liệu và đánh đổi.

10 thg 10, 20266 phút3