Java: разница между сильной / мягкой / слабой / фантомной ссылкой

179

Я прочитал эту статью на эту тему, но я не совсем понимаю. Пожалуйста, дайте мне несколько советов вместе с примерами при описании концепций.

Матиас Браун
источник
4
Я прочитал этот документ, он не помогает мне представить, какая разница. (возможно, потому что это документ с трудом читаемым документом)
14
Если вы прочитали эту статью и до сих пор не поняли, у вас есть конкретные вопросы по этому поводу? Трудно ответить на «пожалуйста, объясните мне Фу», «вот что это значит», «я не понимаю», не уточняя, какие части вы не получите.
ишавит
@LouisWasserman Верхняя ссылка больше не действительна.
Мехрай Малик

Ответы:

142

Java предоставляет два разных типа / класса ссылочных объектов : сильный и слабый . Слабые эталонные объекты можно далее разделить на мягкие и фантомные .

  • сильный
  • слабый
    • мягкий
    • фантом

Давайте идти по пунктам.

Сильный Ссылочный Объект

StringBuilder builder = new StringBuilder();

Это тип / класс ссылочного объекта по умолчанию, если не указано иное: builderэто сильный ссылочный объект. Этот вид ссылки делает указанный объект непригодным для GC. То есть всякий раз, когда на объект ссылается цепочка сильных ссылочных объектов , он не может быть подвергнут сборке мусора.

Слабый эталонный объект

WeakReference<StringBuilder> weakBuilder = new WeakReference<StringBuilder>(builder);

Слабые ссылочные объекты не являются типом / классом ссылочных объектов по умолчанию, и для их использования они должны быть явно указаны, как в примере выше. Этот вид ссылки делает эталонный объект пригодным для GC. То есть, если единственная ссылка, достижимая для StringBuilderобъекта в памяти, на самом деле является слабой ссылкой, то GC разрешается собирать мусорStringBuilder объект . Когда объект в памяти доступен только слабым ссылочным объектам, он автоматически получает право на сборку мусора.

Уровни слабости

Два различных уровня слабости могут быть зачислены: мягкий и призрачный .

Мягкий Reference Object в основном слабая ссылка на объект , который остается в памяти немного больше: обычно, он сопротивляется GC цикла до тех пор память не доступна , и есть риск OutOfMemoryError(в этом случае, он может быть удален).

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

Слабые ссылочные объекты идеально подходят для реализации модулей кеша. Фактически, своего рода автоматическое выселение может быть реализовано, позволяя ГХ очищать области памяти всякий раз, когда объекты / значения больше не достижимы цепочкой сильных ссылок. Примером является WeakHashMap, сохраняющий слабые ключи.

Паоло Мареска
источник
76

Слабая ссылка:

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

Мягкая ссылка:

Мягкая ссылка точно так же, как слабая ссылка, за исключением того, что она меньше стремится выбросить объект, на который она ссылается. Объект, который является только слабо достижимым (самые сильные ссылки на него - WeakReferences), будет отброшен в следующем цикле сборки мусора, но объект, который является легко достижимым, обычно остается на некоторое время.

Призрак Ссылка:

Фантомная ссылка сильно отличается от SoftReference или WeakReference. Его захват его объекта настолько слаб, что вы даже не можете получить объект - его метод get () всегда возвращает ноль. Единственное использование для такой ссылки - отслеживание того, когда она помещается в ReferenceQueue, так как в этот момент вы знаете, что объект, на который она указала, мертв.

Этот текст был извлечен из: https://weblogs.java.net/blog/2006/05/04/understanding-weak-references

Пунит Радж
источник
1
Хотя все в этом ответе выглядит правильно, мне также кажется, что на связанной веб-странице может быть ошибка. Javadoc для пакета java.lang.ref и что для PhantomReference предположить , что объект не мусор не собирает до тех пор , после того, как она уже не «фантомной достижимы», подразумевая , что ( в отличие от SoftReference) а PhantomReference должна быть удалена из очереди до объекта он относится к банке быть сборщиком мусора ... и его постановка в очередь не означает, что связанная память была освобождена.
Теодор Мердок
2
Для справки, я бы предпочел жить в мире, где это сообщение в блоге является правильным.
Теодор Мердок
1
@TheodoreMurdock Javadoc правильный. Фантомная ссылка не препятствует сбору мусора вообще. Как только объект помещен в очередь, он не может быть сохранен даже финализатором, так как финализаторы уже запущены. Он мертв, но еще не ушел.
Лелиэль
@Leliel На самом деле, ссылка фантомная делает на самом деле сбор мусора мешает после его помещён ... Я понял , что это недавно , когда ошибка вызвана очищающей нить к выходу рано. Наличие фантомных ссылок было достаточно, чтобы гарантировать, что каждый объект, на который ссылаются фантомы, был сохранен в моем дампе кучи, недоступен для сбора ... если вам не удается обработать очередь или не удается сделать фантомную ссылку подходящей для gc при обработке очереди ( и не очищайте () фантомную ссылку), тогда утечка памяти будет включать в себя как фантомную ссылку, так и ссылочный объект.
Теодор Мердок
25

Простая разница между SoftReferenceи WeakReferenceобеспечивается Android Developer .

Разница между a SoftReferenceи a WeakReference- это момент времени, когда принимается решение очистить и поставить в очередь ссылку:

  • A SoftReferenceследует очищать и ставить в очередь как можно позже, то есть в случае, если виртуальной машине угрожает нехватка памяти.

  • A WeakReferenceможет быть очищен и помещен в очередь, как только известно, что на него слабо ссылаются.

Мухаммед Набиэль Ариф
источник
16

Три термина, которые вы использовали, в основном связаны с правом объекта на сбор мусора.

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

Мягкая ссылка :: Это более или менее похоже на слабую ссылку. Но вы можете сказать, что он удерживает объект немного сильнее, чем слабая ссылка из сборки мусора.

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

Сильная ссылка :: Это прямо противоположно двум вышеупомянутым ссылкам. Они меньше любят собирать мусор (в основном они никогда не собираются).

Вы можете обратиться к следующей ссылке для получения дополнительной информации:

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

Sabya
источник
3
Я думаю, что это неправильно - «Если сборщики мусора собирают слабые ссылки в самом первом жизненном цикле, они собирают мягкие ссылки в следующем цикле сбора мусора». Это не обязательно так, как вы можете быть настолько уверены, что они происходят при последовательном запуске GC? GC может позволить объектам с мягкой ссылкой жить даже во 2-м и 3-м прогонах. Там нет документации для этого, если есть, пожалуйста, укажите ссылку с указанием.
Саураб Патил
2
Кроме того, ваш ответ немного расплывчатый, посмотрите на это предложение: «Оно более или менее похоже на слабую ссылку. Но вы можете сказать, что он удерживает объект немного сильнее, чем слабая ссылка из сборки мусора. ' - он явно спрашивает о различии, а не сходстве, все эти слова добавляют больше путаницы, чем ясности к теме.
Саураб Патил
@SaurabhPatil - Пропустил ваш комментарий. Здесь идет ответы. 1. «Он явно спрашивает о различиях, а не сходствах» - обратитесь к описанию вопроса (не «только» в заголовке) «Пожалуйста, дайте мне несколько советов, и, пожалуйста, дайте мне пример для описания». 2. «Но вы можете сказать, что он держит объект немного больше…» Я думаю, что SOF дает возможность понизить голосование и дать новые ответы.
Сабиа
14

Эта статья может быть очень полезна для понимания сильных, мягких, слабых и фантомных ссылок.


Чтобы дать вам резюме,

Если у вас есть сильная ссылка на объект, то этот объект никогда не может быть собран / утилизирован GC (сборщик мусора).

Если у вас есть только слабые ссылки на объект (без сильных ссылок), то объект будет восстановлен GC в самом следующем цикле GC.

Если у вас есть только мягкие ссылки на объект (без сильных ссылок), то объект будет восстановлен GC только тогда, когда JVM не хватит памяти.

Мы создаем фантомные ссылки на объект, чтобы отслеживать, когда объект помещается в очередь в ReferenceQueue. Как только вы узнаете, что можете выполнить детальную финализацию. (Это избавит вас от случайного воскрешения объекта, так как фантомные ссылки не дают вам рефератов). Я бы посоветовал вам прочитать эту статью, чтобы получить более подробную информацию об этом.


Таким образом, вы можете сказать, что сильные ссылки имеют максимальную силу (никогда не могут быть собраны GC)

Мягкие ссылки более эффективны, чем слабые (поскольку они могут избежать цикла GC, пока JVM не исчерпает память)

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


Ресторанная аналогия

  • Официант - GC
  • Вы - Объект в куче
  • Зона ресторана / пространство - куча места
  • Новый клиент - новый объект, который хочет столик в ресторане

Теперь, если вы сильный клиент (аналог сильной рекомендации), то даже если в ресторан приходит новый клиент или что-то такое, что всегда радует, вы никогда не покинете свой стол (область памяти в куче). Официант не имеет права говорить вам (или даже просить вас) покинуть ресторан.

Если вы мягкий клиент (аналог мягкого отзыва), то, если в ресторан приходит новый клиент, официант не будет просить вас покинуть стол, если не осталось другой пустой таблицы для размещения нового клиента. (Другими словами, официант попросит вас покинуть стол только в том случае, если заходит новый клиент, и для этого нового клиента не осталось другой таблицы)

Если вы слабый клиент (аналог слабой ссылки), тогда официант по своему желанию может (в любой момент) попросить вас покинуть ресторан: P

Щедрый котари
источник
10

4 степени референции - Strong, Weak, Soft, Phantom

Сильный - это своего рода ссылка, которая делает указанный объект непригодным для GC. Занятия строителей. например - StringBuilder

Слабый - это ссылка, которая имеет право на GC.

Soft - это своего рода ссылка, объект которой подходит для GC, пока память не станет доступной. Лучше всего для кеша изображений. Он будет держать их до тех пор, пока память не станет доступной.

Фантом - это своего рода ссылка, объект которой имеет прямое право на получение GC. Используется только для того, чтобы узнать, когда объект удален из памяти.

использование:

  1. Позволяет определить, когда объект точно удаляется из памяти.

  2. если finalize()метод перегружен, то GC может не произойти своевременно для подходящих объектов GC двух классов. Так что фантомные ссылки делают их подходящими для GC раньше finalize(), поэтому вы можете получить OutOfMemoryErrors, даже если большая часть кучи является мусором.

Слабые ссылки идеально подходят для реализации модулей кеша.

Preetham RU
источник
10

Сильные Ссылки

Это ваши обычные ссылки на объекты, которые мы кодируем ежедневно:

Employee emp = new Employee();

Переменная «emp» содержит строгую ссылку на объект Employee, а объекты, доступные через любую цепочку строгих ссылок, не подходят для сборки мусора. Обычно это то, что вы хотите, но не всегда. Теперь предположим, что мы извлекаем много сотрудников из базы данных в коллекции или на карте, и нам нужно регулярно обрабатывать их, поэтому для поддержания производительности мы будем держать их в кэше.

Насколько это хорошо, но теперь нам нужны разные данные, и нам не нужны эти объекты Employee, и на них нет ссылок нигде, кроме кеша. Что вызывает утечку памяти, потому что эти объекты не используются, но все еще не подходят для сборки мусора, и мы не можем удалить эти объекты из кэша, потому что у нас нет ссылки на них? Так что здесь либо нам нужно очистить весь кеш вручную, что утомительно, либо мы могли бы использовать ссылки другого типа, например, Weak References.

Слабые ссылки

Слабая ссылка не закрепляет объект в памяти, и в следующем цикле GC она будет GC, если на нее не ссылаются другие ссылки. Мы можем использовать класс WeakReference, предоставляемый Java, для создания кэшей вышеуказанного типа, которые не будут хранить объекты, на которые нет ссылок откуда-либо еще.

WeakReference<Cache> cache = new WeakReference<Cache>(data);

Для доступа к данным вам нужно вызвать cache.get (). Этот вызов get может вернуть null, если слабая ссылка была собрана сборщиком мусора: вы должны проверить возвращаемое значение, чтобы избежать NPE. Java предоставляет коллекции, которые используют слабые ссылки, например, класс WeakHashMap хранит ключи (не значения) как слабые ссылки. Если ключ GC'd, то значение будет автоматически удалено и с карты.

Поскольку слабые ссылки тоже являются объектами, нам нужен способ их очистки (они больше не нужны, когда объект, на который они ссылались, был GC'd). Если вы передадите ReferenceQueue в конструктор для слабой ссылки, сборщик мусора добавит эту слабую ссылку в ReferenceQueue до того, как они будут завершены или GC'd. Вы можете периодически обрабатывать эту очередь и обрабатывать мертвые ссылки.

Мягкие ссылки

SoftReference похож на WeakReference, но он с меньшей вероятностью будет собирать мусор. Мягкие ссылки очищаются по усмотрению сборщика мусора в ответ на запрос памяти. Виртуальная машина гарантирует, что все мягкие ссылки на мягко достижимые объекты будут очищены до того, как она выдаст OutOfMemoryError.

Призрачные Ссылки

Фантомные ссылки - самый слабый из всех ссылочных типов, вызов get для них всегда будет возвращать ноль. На объект ссылаются фантомно после того, как он был завершен, но до того, как его выделенная память была освобождена, в отличие от слабых ссылок, которые ставятся в очередь до того, как они завершены, или ссылки фантома GC'd редко используются.

Так чем они полезны? Когда вы создаете фантомную ссылку, вы всегда должны передавать ReferenceQueue. Это означает, что вы можете использовать фантомную ссылку, чтобы увидеть, когда ваш объект GC'd.

Эй, так что, если слабые ссылки ставятся в очередь, когда они считаются финализированными, но еще не GC'd, мы можем создать новую сильную ссылку на объект в блоке финализатора и предотвратить объект GC'd. Да, вы можете, но вы, вероятно, не должны этого делать. Для проверки этого случая цикл GC будет происходить как минимум дважды для каждого объекта, если этот объект не доступен только по фантомной ссылке. Вот почему вы можете исчерпать кучу, даже если ваша память содержит много мусора. Призрачные ссылки могут предотвратить это.

Вы можете прочитать больше в моей статье Типы ссылок в Java (Strong, Soft, Weak, Phantom) .

Нареш Джоши
источник
Вы писали, что в следующем цикле слабые ссылки будут собираться с помощью GC, если они не связаны с другими ссылками ... но не должно ли происходить то же самое с ссылками stron? если к строновой ссылке не обращаются каким-либо образом, то очищается ... тогда, если так, то где опять разница? #confused
filemonczyk
1
Если объект получает ссылку, скажем, из s1 (сильный) и s2 (сильный), объект не будет иметь право на сборку мусора, пока не будут разыменованы и s1, и s2, но если объект получает ссылку из s1 (слабый) и s2 ( strong) тогда объект будет иметь право на сборку мусора в следующем цикле GC, когда на него разыменовывается только s2, поскольку s1 является слабой ссылкой, а если у объекта нет какой-либо другой ссылки, кроме слабой, он подходит для GC
Нареш Джоши