2012-02-06 36 views
7

Javadocs cho biết "Khi một khóa đã bị loại bỏ, mục nhập của nó là có hiệu lực bị xóa khỏi bản đồ".WeakHashMap và giá trị tham chiếu mạnh

Nhưng trừ khi có một chuỗi khác đôi khi xóa các mục nhập Map.Entry như vậy, các đối tượng giá trị có được tham chiếu mạnh mẽ bởi bản đồ không? Nhưng vì không có chuỗi chạy như vậy, chỉ có các lời gọi phương thức get mới có thể loại bỏ các mục nhập đó - mỗi lần một.

Tôi hầu như luôn sử dụng WeakHashMap<K, WeakReference<V>> vì lý do đó. Tại sao họ không làm cho rằng hành vi mặc định - các giá trị như là các tham chiếu yếu?

+0

http://stackoverflow.com/questions/2473410/question-about-weakhashmap gần giống như một câu hỏi. Nhưng tôi muốn biết nếu khẳng định của tôi là chính xác: một mục sẽ bị xóa chỉ khi get() phát hiện ra rằng khóa đã được gc'ed, mà thẳng thắn dường như không có giá trị lớn trừ khi tôi sử dụng WeakReferences làm giá trị. –

+0

Vâng, nó chỉ được bình chọn. Nếu bạn muốn một cái gì đó khác nhau, hãy viết phiên bản của riêng bạn. –

+2

Nếu bạn cần một cái gì đó khác nhau, sử dụng một thư viện - viết của riêng bạn là siêu khó khăn. Ổi có 'MapMaker', cho phép bạn định cấu hình sức mạnh của các tham chiếu khóa và giá trị: http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/MapMaker. html –

Trả lời

8

Hàng đợi tham chiếu được sử dụng để tự động xóa mục nhập.

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/ReferenceQueue.html

hàng đợi tham khảo, mà đăng ký đối tượng tham chiếu được nối bởi các nhà sưu tập rác sau khi thay đổi reachability thích hợp được phát hiện.

Về cơ bản, tài liệu tham khảo yếu là phần cốt lõi của bộ thu gom rác, vì vậy khi quét GC xảy ra, tham chiếu không được sử dụng sẽ được tìm thấy và xếp hàng đợi và hành động có thể được thực hiện dựa trên nội dung của các hàng đợi đó.

Chủ đề có thể ngồi trên phương thức remove của hàng đợi để được cảnh báo khi cần dọn dẹp hoặc poll hàng đợi.

"Java theory and practice: Plugging memory leaks with weak references" giải thích:

Việc thực hiện WeakHashMap minh họa một thành ngữ phổ biến với sự tham khảo yếu - rằng một số đối tượng bên trong mở rộng WeakReference.

...

WeakHashMap sử dụng tài liệu tham khảo yếu để giữ phím bản đồ, cho phép các đối tượng chính được thành rác khi chúng không còn được sử dụng bởi các ứng dụng, và việc thực hiện get() có thể nói với một ánh xạ trực tiếp từ một số tiền chết là WeakReference.get() trả về null. Nhưng đây chỉ là một nửa những gì cần thiết để duy trì mức tiêu thụ bộ nhớ của Map trong suốt thời gian tồn tại của ứng dụng; một cái gì đó cũng phải được thực hiện để cắt tỉa các mục chết từ Bản đồ sau khi đối tượng khóa đã được thu thập. Nếu không, Bản đồ sẽ chỉ điền vào các mục tương ứng với các phím chết. Và mặc dù điều này sẽ không hiển thị với ứng dụng, nó vẫn có thể khiến ứng dụng hết bộ nhớ vì các đối tượng Map.Entry và value sẽ không được thu thập, ngay cả khi khóa là.

...

hàng đợi tham khảo là phương tiện chủ yếu thu gom rác của ăn lại thông tin cho các ứng dụng về vòng đời đối tượng. Tham chiếu yếu có hai hàm tạo: một chỉ lấy tham chiếu làm đối số và đối số còn lại có một hàng tham chiếu. Khi một tham chiếu yếu đã được tạo với một hàng tham chiếu liên quan và tham chiếu trở thành một ứng cử viên cho GC, đối tượng tham chiếu (không phải là tham chiếu) được xếp vào hàng đợi tham chiếu sau khi tham chiếu bị xóa.Sau đó, ứng dụng có thể truy xuất tham chiếu từ hàng đợi tham chiếu và tìm hiểu rằng tham chiếu đã được thu thập để nó có thể thực hiện các hoạt động dọn dẹp liên quan, chẳng hạn như xóa các mục nhập cho các đối tượng đã rơi ra khỏi bộ sưu tập yếu. (Hàng đợi tham khảo cung cấp các phương thức dequeuing giống như BlockingQueue - thăm dò, chặn đúng lúc, và chặn untimed.)

EDIT:

Ngay cả với hàng đợi, bản đồ yếu vẫn có thể bị rò rỉ. Ephemerons là một nỗ lực để giải quyết trường hợp khóa yếu tham chiếu đến giá trị được giữ vững có tham chiếu đến khóa. Chúng không thể thực hiện được trong java.

Ephemerons giải quyết vấn đề thường được tìm thấy khi cố gắng "đính kèm" thuộc tính vào đối tượng bằng cách sử dụng sổ đăng ký. Khi một số thuộc tính nên được gắn vào một đối tượng, thuộc tính nên (về mặt hành vi GC) thường có thời gian sống mà một biến cá thể của đối tượng này sẽ có. Tuy nhiên, điều này rất phức tạp do có một hiệp hội bên ngoài giữa các đối tượng và tài sản của mình như:

property --------- registry --------- association --------- object 

Ở đây, registry (bên thứ ba) sẽ tổ chức vào hiệp hội riêng của mình mà sẽ yêu cầu loại bỏ bằng tay từ registry (thay vì thu gom rác tự động). Mặc dù vấn đề này luôn có thể được giải quyết trong bất kỳ tình huống cụ thể nào bằng cách sử dụng một trong các kiểu kết hợp yếu khác nhau, việc chọn loại liên kết 'đúng' phụ thuộc vào nhiều yếu tố khác nhau.

Ephemerons giải quyết vấn đề này bằng cách xác định rằng 'nội dung' (giá trị) của một ephemeron sẽ được tổ chức mạnh mẽ cho đến khi khóa được biết là rác được thu thập. Từ đó trở đi, nội dung của phù thủy sẽ được tổ chức yếu ớt. Do đó, nội dung của một ephemeron có thể trở thành đủ điều kiện cho việc thu gom rác nếu và chỉ khi khóa là thu gom rác là hành vi chính xác mà chúng ta quan sát cho một biến mẫu của đối tượng.

+0

Quên về khả năng của hàng đợi tham chiếu để gọi móc của chúng ta. –

+0

Tôi tìm thấy từ liên kết của bạn "WeakHashMap có một phương thức riêng gọi là expungeStaleEntries() được gọi trong hầu hết các hoạt động Bản đồ." hữu ích. Và tự hỏi nếu sinh ra một sợi mà thực sự sẽ ngăn chặn đọc trên hàng đợi tham khảo có thể là một ý tưởng tốt hơn. Có lẽ đó là những gì MapMaker của Guava làm. –

+1

@ UstamanSangat, tôi không biết MapMaker làm gì, nhưng có thể expungeStaleEntries() thăm dò hàng đợi tham chiếu để phân bổ dọn dẹp với việc sử dụng bản đồ. Tôi sẽ thử sử dụng một cái gì đó như MapMaker trước khi mucking xung quanh với việc thực hiện làm sạch chính của riêng tôi.Btw, tôi đã thêm một bản chỉnh sửa chỉ ra những cách bạn có thể làm rò rỉ bộ nhớ ngay cả khi sử dụng các bản đồ khóa yếu. –

Các vấn đề liên quan