2012-02-06 3 views
7

Javadocs говорит: «Когда ключ был отброшен, его запись эффективно удалена с карты».WeakHashMap и строгое ссылочное значение

Но если нет другой нити, которая иногда удаляет такие записи Map.Entry, не будут ли ссылки на объекты объектов сильно привязаны к карте? Но поскольку такой поток не работает, только вызовы метода get могут удалять такие записи - по одному за раз.

Я почти всегда использую WeakHashMap<K, WeakReference<V>> по этой причине. Почему бы им не сделать так, чтобы поведение по умолчанию - значения как слабые ссылки тоже?

+0

http://stackoverflow.com/questions/2473410/question-about-weakhashmap - почти идентичный вопрос. Но я хотел знать, верно ли мое утверждение: запись будет удалена только тогда, когда get() обнаруживает, что ключ был gc'ed, что, откровенно говоря, не имеет большого значения, если я не использую WeakReferences в качестве значений. –

+0

Да, это просто опрошено. Если вы хотите что-то другое, напишите свою собственную версию. –

+2

Если вам нужно что-то другое, используйте библиотеку - писать свой собственный очень сложно. В Guava есть «MapMaker», который позволяет вам настроить силу ссылок на ключевые слова и значения: http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/MapMaker. html –

ответ

8

Опорные очереди используются для автоматического удаления записей.

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

Ссылочные очереди, к которой зарегистрированы ссылки на объекты добавляются сборщиком мусора после того, как соответствующие изменения достижимости обнаружены.

В основном, слабые ссылки являются основной частью сборки мусора, поэтому, когда GC развертка происходит, неиспользованные ссылки найдены и положить на очередь, а затем могут быть приняты меры на основе содержания этих очередей.

Поток может помещаться в очередь remove. Очередь должна быть предупреждена при необходимости очистки или poll очереди.

"Java theory and practice: Plugging memory leaks with weak references" объясняет:

Реализация WeakHashMap иллюстрирует общие идиомы со слабыми ссылками - то внутренний объект расширяет WeakReference.

...

WeakHashMap использует слабые ссылки для хранения ключей карт, которые не позволяют ключевые объекты, подлежащие сборке мусора, когда они больше не используются приложением, а get() реализация может сказать живое отображение из мертвый один от WeakReference.get() возвращает null. Но это лишь половина того, что необходимо для увеличения потребления памяти карты на протяжении всего срока службы приложения; необходимо также сделать так, чтобы обрезать мертвые записи с Карты после того, как был собран основной объект. В противном случае Карта просто заполнила бы записи, соответствующие мертвым клавишам. И хотя это будет невидимым для приложения, оно все равно может привести к тому, что приложение закончится из-за нехватки памяти, поскольку объекты Map.Entry и value не будут собраны, даже если ключ.

...

Эталонные очереди основное средство сборщика мусора для предоставления обратной информации приложению о жизненном цикле объектов. Слабые ссылки имеют два конструктора: один принимает только референт в качестве аргумента, а другой также принимает ссылочную очередь. Когда слабая ссылка была создана с соответствующей ссылочной очередью, и референт становится кандидатом для GC, ссылочный объект (а не референт) помещается в очередь в очереди ссылок после удаления ссылки.Затем приложение может получить ссылку из ссылочной очереди и узнать, что референт собран, чтобы он мог выполнять связанные действия по очистке, такие как изъятие записей для объектов, которые выпадали из слабой коллекции. (Очереди ссылок имеют те же способы, как BlockingQueue извлечение из очереди - опрашиваемого, приуроченная блокировки и бессрочные блокировки.)

EDIT:

Даже с очередями, слабые карты могут еще течь. Ephemerons - это попытка решить случай, когда слабый ключ ссылается на сильно удерживаемое значение, которое ссылается на ключ. Они не реализуются в java.

Эфемероны решают проблему, которая обычно встречается при попытке «прикрепить» свойства к объектам с помощью реестра. Когда какое-либо свойство должно быть привязано к объекту, свойство должно (в терминах поведения GC) обычно иметь срок жизни, который будет иметь переменная экземпляра этого объекта. Однако это осложняется наличием внешней связи между объектом и его собственности, таких как:

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

Здесь реестр (третья сторона) будет держаться на самой ассоциации, которая потребует ручного удаления из реестра (вместо автоматического сбора мусора). Хотя эта проблема всегда может быть решена в любой конкретной конкретной ситуации, используя один из различных типов слабых ассоциаций, выбор «правильного» типа ассоциации зависит от множества факторов, некоторые из которых могут динамически меняться.

Эфемероны решают эту проблему, определяя, что «содержимое» (значение) эфемерона будет удерживаться сильно до тех пор, пока ключ, как известно, не будет собран в мусор. С этого момента содержимое эфемерона будет слабо удерживаться. Поэтому содержимое эфемерона может стать подходящим для сбора мусора, если и только если ключ является сборкой мусора, который является точным поведением, которое мы будем наблюдать за переменной экземпляра объекта.

+0

Забыл о возможности ссылочной очереди вызвать наш собственный крючок. –

+0

Я нашел по вашей ссылке «WeakHashMap имеет частный метод, называемый expungeStaleEntries(), который вызывается во время большинства операций с Map». быть полезным. И интересно, может ли идея создания нереста, которая на самом деле делает блокирование чтения в ссылочной очереди, может быть лучшей идеей. Возможно, это то, что делает MapMaker от Guava. –

+1

@UstamanSangat, я не знаю, что делает MapMaker, но возможно expungeStaleEntries() опроса ссылочной очереди, чтобы амортизировать очистку с использованием карты. Я бы попытался использовать что-то вроде MapMaker, прежде чем обманывать себя с помощью моей собственной очистки ключа.Кстати, я добавил редактирование, в котором указываются способы утечки памяти даже при использовании слабых ключевых карт. –