WeakHashMap và Weak Reference Trong Java
Giới thiệu
Trong thư viện Collection của Java, có một lớp đặc biệt: WeakHashMap. Về hoạt động nói chung nó rất giống với HashMap, đều có chức năng quản lý key, value như thêm, bớt, truy xuất value theo key… Vậy khác biệt của WeakHashMap so với HashMap là gì? Đó chính là khả năng phối hợp của WeakHashMap với garbage collector nhằm loại bỏ khả năng leak memory có thể xảy ra với HashMap. Trong bài viết này, chúng ta sẽ tìm hiểu WeakHashMap là gì, cách hoạt động của nó như thế nào, và cách nó xóa bỏ những entry không dùng đến ra sao.
Mở đầu
Thử tưởng tượng một tình huống như thế này: bạn muốn sử dụng một class nào đó, nhưng không thể extend được nó (ví dụ trường hợp đơn giản nhất là class đó được chỉ định là final). Vậy bạn làm gì khi muốn thêm property cho object thuộc class đó?
Ví dụ, bạn muốn sử dụng một class Product mà không thể extend được. Bây giờ muốn thêm serialNumber cho product đó, ứng cử viên hàng đầu là HashMap, bạn có thể tạo một cặp key là Product object, value là serialNumber:
1 2 3 4 5 6 |
|
Đoạn code trên có vẻ đã hoàn thành mục tiêu thêm thuộc tính cho Product object, nhưng có vấn đề gì ở đây không? Cách giải quyết này gặp phải vấn đề liên quan đến việc giải phóng bộ nhớ. Vì HashMap sử dụng strong reference để trỏ đến Product object, nên khi trong chương trình không còn reference nào đến Product object nữa, garbage collector nhận thấy vẫn còn strong reference ở trong HashMap, nên nó không giải phóng object này nữa. Lâu dần, sẽ xuất hiện hiện tượng Leak Memory: ta không thể giải phóng được cặp key, value nằm trong HashMap, khi mà HashMap còn được sử dụng (để hiểu rõ hơn, bạn có thể xem ví dụ demo ở cuối bài).
Nhân đây, xin giải thích thêm về Strong reference. Đây là Java reference bình thường mà ta thường sử dụng. Như ví dụ sau:
1
|
|
sẽ tạo một object String và lưu một strong reference đến nó vào biến serialNo. Ta cần phải để ý mới quan hệ giữa strong reference và garbage collector như sau: Nếu một object được trỏ đến qua một số strong references, object đó sẽ không được garbage collector để ý đến.
WeakHashMap
Trái ngược lại với strong reference là weak reference. *Weak reference** sẽ không thể cản trở garbage collector giải phóng object khỏi memory. Khai báo như sau:
1
|
|
Sau đó, ta có thể truy cập đến Product object thông qua việc gọi method weakProduct.get(). Tuy nhiên, ta cần phải chú ý khi gọi method này. Vì weak reference không đủ khả năng chặn quá trình garbage collection, nên đến một cycle nào đó, garbage collector sẽ giải phóng Product object (khi không còn strong reference nào đến nó) , và bạn sẽ thấy weakProduct.get() đột nhiên trả về null.
Quay trở lại với ví dụ Product ở trên, ta giải quyết vấn đề đã nêu bằng cách sử dụng WeakHashMap class. WeakHashMap hoạt động y hệt như HashMap, chỉ khác là key được refer đến bằng weak reference. Lúc này, khi một object chỉ reachable bởi WeakReference, garbage collector sẽ giải phóng object, đồng thời sẽ đặt weak reference trỏ đến object kia vào một queue. WeakHashMap sẽ định kì kiểm tra queue này xem có weak reference nào mới đến không. Nếu thấy một weak reference trong queue, nghĩa là key đã không được ai sử dụng nữa và nó đã bị garbage collector “tịch thu”. Lúc đó, WeakHashMap sẽ bỏ entry liên quan đi. No more memory leak ! :)
Demo
Lý thuyết là vậy. Để dễ hiểu hơn, quan sát đoạn demo WeakHashMap sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
|
Chạy đoạn code trên: kết quả như sau:
1 2 3 4 5 6 |
|
thay WeakHashMap bằng HashMap, kết quả sẽ như thế nào?
1 2 3 4 5 6 7 |
|
Bạn đã thấy điểm khác biệt? Sau một khoảng thời gian, WeakHashMap sẽ bỏ đi entry tương ứng với weak reference. Còn HashMap, vì là strong reference, trong map sẽ luôn chứa cặp phần tử (someDataObject, value) mặc dù bên ngoài someDataObject đã set là null.
Kết luận
Bài viết này đã trình bày tác dụng của một lớp trong Collection của Java: WeakHashSet. Đồng thời, bài viết cũng giới thiệu weak reference và strong reference và mối quan hệ của chúng với Java garbage collector.
Tham khảo
- Core Java Volume I–Fundamentals
- http://docs.oracle.com/javase/6/docs/api/java/util/WeakHashMap.html