Понимание справочных классов Java: SoftReference, WeakReference и PhantomReference
Может кто-нибудь объяснить разницу между тремя ссылочными классами (или опубликовать ссылку на хорошее объяснение)? SoftReference
> WeakReference
> PhantomReference
, но когда я буду использовать каждый? Почему есть WeakHashMap
но нет SoftHashMap
или же PhantomHashMap
?
И если я использую следующий код...
WeakReference<String> ref = new WeakReference<String>("Hello!");
if (ref != null) { // ref can get collected at any time...
System.gc(); // Let's assume ref gets collected here.
System.out.println(ref.get()); // Now what?!
}
...что просходит? Должен ли я проверить, ref
равен нулю перед каждым утверждением (это неправильно, но что мне делать)? Извините за быстрые вопросы, но у меня проблемы с пониманием Reference
занятия... Спасибо!
4 ответа
Документация библиотеки Java для java.lang.ref
Пакет характеризует уменьшение силы трех явных ссылочных типов.
Вы используетеSoftReference
когда вы хотите, чтобы указанный объект оставался в живых до тех пор, пока у хост-процесса не останется мало памяти. Объект не будет пригоден для сбора, пока сборщику не понадобится освободить память. Слабо сказано, обязательныйSoftReference
означает "Закрепить объект, пока вы не можете больше."
В отличие от этого, используйтеWeakReference
когда вы не хотите влиять на время жизни ссылочного объекта; Вы просто хотите сделать отдельное утверждение о ссылочном объекте, пока он остается живым. Право на получение объекта не зависит от наличия связанных WeakReference
s. Хорошее использование для чего-то вроде внешнего сопоставления от экземпляра объекта к связанному свойству, где свойство нужно записывать только до тех пор, пока связанный объект жив,WeakReference
с иWeakHashMap
,
Последний- PhantomReference
- сложнее охарактеризовать. подобно WeakReference
такой предел PhantomReference
не оказывает влияния на время жизни ссылочного объекта. Но в отличие от других ссылочных типов, нельзя даже разыменовать PhantomReference
, В некотором смысле, это не указывает на то, на что он указывает, насколько звонящие могут сказать. Это просто позволяет связать некоторые связанные данные с указанным объектом - данные, которые могут быть позже проверены и применены, когда PhantomReference
встает в очередь в связанныхReferenceQueue
, Обычно каждый получает тип отPhantomReference
и включает в себя некоторые дополнительные данные в этом производном типе. К сожалению, для использования такого производного типа требуется некоторое уныние.
В вашем примере кода это неref
ссылка (или, если хотите, "переменная"), которая может быть нулевой. Скорее, это значение, полученное путем вызоваReference#get()
это может быть нулевым. Если он окажется нулевым, вы опоздали; указанный объект уже находится на пути к сбору:
final String val = ref.get();
if (null != val)
{
// "val" is now pinned strongly.
}
else
{
// "val" is already ready to be collected.
}
Ссылка: https://community.oracle.com/blogs/enicholas/2006/05/04/understanding-weak-references
PhantomHashMap
не будет работать очень хорошо, как get
всегда возвращается null
для фантомных ссылок.
Кеши сложны, поэтому SoftHashMap
может работать не так хорошо, как вы думаете. Тем не менее, я считаю, что библиотека коллекций Google содержит общую реализацию карты ссылок.
Вы должны всегда проверять это get
возвращает неnull
, (Обратите внимание, что не проверяя, что Reference
Сама ссылка неnull
.) В случае интернированных строк это всегда будет, но (как всегда) не пытайтесь быть "умными" в этом.
Следует также упомянуть, как указано в комментарии Чыонг Суан Тинь, здесь: http://blog.yohanliyanage.com/2010/10/ktjs-3-soft-weak-phantom-references/
Эта JRockit JVM реализует слабые / мягкие / фантомные ссылки иначе, чем Sun JVM.
String str = new String("hello, world");
WeakReference<String> ref = new WeakReference<String>(str);
str = null;
if (ref != null) {
System.gc();
System.out.println(ref.get());
}
В этом случае он будет выводить ноль. Призыв к System.gc()
здесь важно