Понимание справочных классов Java: SoftReference, WeakReference и PhantomReference - PullRequest
79 голосов
/ 25 июля 2010

Может кто-нибудь объяснить разницу между тремя справочными классами (или опубликовать ссылку на хорошее объяснение)?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 ]

58 голосов
/ 25 июля 2010

Документация библиотеки Java для пакета java.lang.ref характеризует снижение силы трех явных ссылочных типов.

Вы используете SoftReference, когда хотите, чтобы указанный объект оставался в живых до тех пор, пока процесс хоста не исчерпает память. Объект не будет иметь права на коллекцию, пока сборщику не понадобится для освобождения памяти. Проще говоря, привязка SoftReference означает «Закрепить объект, пока вы больше не сможете».

Напротив, используйте WeakReference, если вы не хотите влиять на время жизни ссылочного объекта; Вы просто хотите сделать отдельное утверждение о объекте, на который ссылаются, до тех пор, пока он остается живым. Право на получение объекта не зависит от наличия связанных WeakReference s. Нечто подобное внешнему отображению экземпляра объекта в связанное свойство, где свойство нужно записывать только до тех пор, пока связанный объект жив, хорошо подходит для WeakReference s и 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.
}
6 голосов
/ 25 июля 2010

Ссылка: https://community.oracle.com/blogs/enicholas/2006/05/04/understanding-weak-references

PhantomHashMap не будет работать очень хорошо, поскольку get всегда возвращает null для фантомных ссылок.

Кэши сложны, поэтому SoftHashMap может работать не так хорошо, как вы думаете.Тем не менее, я считаю, что библиотека коллекций Google содержит общую карту ссылок.

Вы всегда должны проверять, что get возвращает не-null.(Обратите внимание, что не проверять, что сама ссылка Reference не является * null.) В случае интернированных строк это всегда будет, но (как всегда) не пытайтесь быть "умными" в этом.

3 голосов
/ 02 августа 2013

Также следует упомянуть, как указано в комментарии Труонга Сюань Тинь, здесь: http://blog.yohanliyanage.com/2010/10/ktjs-3-soft-weak-phantom-references/

Эта JRockit JVM реализует слабые / мягкие / фантомные ссылки иначе, чем Sun JVM.

0 голосов
/ 04 марта 2016
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() важен здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...