Какая разница между java.lang.ref.WeakReference
а java.lang.ref.SoftReference
?
Какая разница между java.lang.ref.WeakReference
а java.lang.ref.SoftReference
?
Ответы:
От понимания слабых ссылок , Итан Николас:
Слабые ссылки
Слабая ссылка , попросту говоря, это ссылка , которая не является достаточно сильным , чтобы заставить объект оставаться в памяти. Слабые ссылки позволяют вам использовать способность сборщика мусора определять доступность для вас, поэтому вам не придется делать это самостоятельно. Вы создаете слабую ссылку, как это:
WeakReference weakWidget = new WeakReference(widget);
а затем в другом месте кода вы можете использовать,
weakWidget.get()
чтобы получить фактическийWidget
объект. Конечно, слабая ссылка недостаточно сильна, чтобы предотвратить сборку мусора, поэтому вы можете обнаружить (если нет сильных ссылок на виджет), которыйweakWidget.get()
внезапно начнет возвращатьсяnull
....
Мягкие ссылки
Мягкая ссылка точно как слабая ссылка, за исключением того, что он менее стремится выбросить объект , к которому оно относится. Объект, который является только слабо достижимым (самые сильные ссылки на него
WeakReferences
), будет отброшен на следующем цикле сборки мусора, но объект, который легко доступен, обычно остается на некоторое время.
SoftReferences
не обязаны вести себя иначеWeakReferences
, но на практике легко достижимые объекты обычно сохраняются, пока в изобилии имеется память. Это делает их отличной основой для кэша, такого как описанный выше кэш изображений, поскольку вы можете позволить сборщику мусора беспокоиться как о достижимости объектов (объект с высокой степенью доступности никогда не будет удален из кэша), так и о том, насколько плохо нужна память, которую они потребляют.
А Питер Кесслер добавил в комментарии:
Sun JRE рассматривает SoftReferences иначе, чем WeakReferences. Мы пытаемся удержать объект, на который ссылается SoftReference, если нет давления на доступную память. Одна деталь: политика для JRE "-client" и "-server" различна: JRE -client старается сохранить ваш размер небольшим, предпочитая очищать SoftReferences, а не расширять кучу, тогда как JRE -server старается сохранить ваш высокая производительность, предпочитая расширять кучу (если возможно), а не очищать SoftReferences. Один размер не подходит для всех.
Слабые ссылки собраны с нетерпением. Если GC обнаружит, что объект является слабо достижимым (достижимым только по слабым ссылкам), он немедленно очистит слабые ссылки на этот объект. Таким образом, они хороши для хранения ссылки на объект, для которого ваша программа также хранит (строго ссылаются) «связанную информацию», например, кэшированную информацию об отражении класса, или оболочку для объекта и т. Д. Все, что делает нет смысла сохранять после того, как объект, с которым он связан, является GC-ed. Когда слабая ссылка очищается, она помещается в очередь ссылок, которую ваш код где-то опрашивает, а также отбрасывает связанные объекты. То есть вы сохраняете дополнительную информацию об объекте, но эта информация не нужна, когда объект, на который он ссылается, исчезает. Фактически, в некоторых ситуациях вы можете даже создать подкласс WeakReference и сохранить связанную дополнительную информацию об объекте в полях подкласса WeakReference. Другое типичное использование WeakReference в сочетании с Maps для хранения канонических экземпляров.
SoftReferences, с другой стороны, хороши для кэширования внешних восстанавливаемых ресурсов, поскольку GC обычно задерживает их очистку. Однако гарантируется, что все SoftReferences будут очищены до того, как будет выдан OutOfMemoryError, поэтому они теоретически не могут вызвать OOME [*].
Типичным примером использования является сохранение проанализированной формы содержимого из файла. Вы реализуете систему, в которой вы загружаете файл, анализируете его и сохраняете SoftReference для корневого объекта анализируемого представления. В следующий раз, когда вам понадобится файл, вы попытаетесь получить его через SoftReference. Если вы можете получить его, вы избавили себя от другой загрузки / разбора, и если GC тем временем очистил его, вы перезагрузите его. Таким образом, вы используете свободную память для оптимизации производительности, но не рискуете OOME.
Теперь для [*]. Хранение SoftReference не может вызвать OOME само по себе. Если, с другой стороны, вы по ошибке используете SoftReference для задачи, которая предназначена для использования WeakReference (а именно, вы храните информацию, связанную с объектом, как-то строго ссылающейся, и отбрасываете ее, когда очищается объект Reference), вы можете запустить OOME как Ваш код, который опрашивает ReferenceQueue и удаляет связанные объекты, может не запуститься своевременно.
Таким образом, решение зависит от использования - если вы кэшируете информацию, которую дорого построить, но тем не менее восстанавливаемую из других данных, используйте мягкие ссылки - если вы сохраняете ссылку на канонический экземпляр некоторых данных, или вы хотите иметь ссылку на объект, не «владея» им (таким образом предотвращая его GC'd), используйте слабую ссылку.
WeakReference
является то, что в тех местах, где его следует использовать, тот факт, что он может оставаться действительным в течение некоторого времени после того, как ссылка выходит из области видимости, может быть допустимым, но нежелательным.
WeakReference
которое заключается в наблюдении за запусками GC. См. Подробности: stackoverflow.com/a/46291143/632951
На Java ; Порядок от самого сильного до самого слабого, есть: сильный, мягкий, слабый и призрачный
Сильная ссылка нормальная ссылка , которая защищает упомянутый объект из коллекции с помощью ОГО. т.е. никогда не собирает мусор.
Мягкая ссылка имеет право для сбора сборщика мусора, но , вероятно , не будет собираться , пока его память не требуется. т.е. мусор собирает раньше OutOfMemoryError
.
Слабая ссылка является ссылкой , что не защищает объект , на который ссылается из коллекции с помощью ГХ. т.е. мусор собирается, когда нет сильных или мягких рефсов.
Фантом ссылка является ссылка на объект phantomly ссылается после того, как она была завершена, но до его выделенная память была утилизирована.
Аналогия. Предположим, JVM - это королевство, Object - король королевства, а GC - атакующий королевства, который пытается убить короля (объект).
until memory is available
не имеет смысла. Вы имеете в виду is eligible for collection by garbage collector, but probably won't be collected until its memory is needed for another use
?
Слабая ссылка http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html
Принцип: weak reference
связан со сборкой мусора. Обычно объект, имеющий один или несколько объектов, не reference
будет иметь права на сборку мусора.
Вышеуказанный принцип не применим, когда он есть weak reference
. Если объект имеет слабую ссылку на другие объекты, он готов к сборке мусора.
Давайте посмотрим на приведенный ниже пример: у нас есть объект Map
with, где Key ссылается на объект.
import java.util.HashMap;
public class Test {
public static void main(String args[]) {
HashMap<Employee, EmployeeVal> aMap = new
HashMap<Employee, EmployeeVal>();
Employee emp = new Employee("Vinoth");
EmployeeVal val = new EmployeeVal("Programmer");
aMap.put(emp, val);
emp = null;
System.gc();
System.out.println("Size of Map" + aMap.size());
}
}
Теперь во время выполнения программы мы сделали emp = null
. Map
Холдинг ключ не имеет смысла здесь , как это null
. В описанной выше ситуации объект не является сборщиком мусора.
WeakHashMap
WeakHashMap
это тот, где записи ( key-to-value mappings
) будут удалены, когда уже невозможно получить их из Map
.
Позвольте мне показать выше пример с WeakHashMap
import java.util.WeakHashMap;
public class Test {
public static void main(String args[]) {
WeakHashMap<Employee, EmployeeVal> aMap =
new WeakHashMap<Employee, EmployeeVal>();
Employee emp = new Employee("Vinoth");
EmployeeVal val = new EmployeeVal("Programmer");
aMap.put(emp, val);
emp = null;
System.gc();
int count = 0;
while (0 != aMap.size()) {
++count;
System.gc();
}
System.out.println("Took " + count
+ " calls to System.gc() to result in weakHashMap size of : "
+ aMap.size());
}
}
Вывод: Взял, 20 calls to System.gc()
чтобы привести aMap size
к: 0.
WeakHashMap
имеет только слабые ссылки на ключи, а не сильные ссылки, как другие Map
классы. Существуют ситуации, о которых вам нужно позаботиться, когда значение или ключ имеют строгую ссылку, хотя вы и использовали WeakHashMap
. Этого можно избежать, обернув объект в WeakReference .
import java.lang.ref.WeakReference;
import java.util.HashMap;
public class Test {
public static void main(String args[]) {
HashMap<Employee, EmployeeVal> map =
new HashMap<Employee, EmployeeVal>();
WeakReference<HashMap<Employee, EmployeeVal>> aMap =
new WeakReference<HashMap<Employee, EmployeeVal>>(
map);
map = null;
while (null != aMap.get()) {
aMap.get().put(new Employee("Vinoth"),
new EmployeeVal("Programmer"));
System.out.println("Size of aMap " + aMap.get().size());
System.gc();
}
System.out.println("Its garbage collected");
}
}
Мягкие ссылки.
Soft Reference
немного сильнее, что слабая ссылка. Мягкая ссылка позволяет собирать мусор, но умоляет сборщик мусора очистить его, только если нет другой опции.
Сборщик мусора не собирает агрессивно доступные объекты, как это происходит со слабо достижимыми объектами - вместо этого он собирает объекты, которые легко достижимы, только если ему действительно «нужна» память. Мягкие ссылки - это способ сказать сборщику мусора: «Пока память не слишком тесная, я бы хотел сохранить этот объект. Но если память становится действительно тесной, продолжайте собирать ее, и я разберусь» с этим. " Сборщик мусора требуется очистить все мягкие ссылки, прежде чем он может бросить OutOfMemoryError
.
NullPointerException
по прибытию aMap.get().put(...)
.
WeakHashMap
пример (поскольку это первый пример, демонстрирующий слабое поведение). Посмотрите на документ «WeakHashMap»: "An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. "
весь смысл использования WeakHashMap заключается в том, что вам не нужно объявлять / передавать WeakReference; WeakHashMap делает это для вас, внутренне. docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html
WeakHashMap
в действии, с примером приложения, показывающего, как удаляются записи только после выполнения сборки мусора, см. Мой ответ на вопрос: « Всегда ли WeakHashMap постоянно растет, или он очищает ключи мусора? ,
Единственная реальная разница между мягкой ссылкой и слабой ссылкой заключается в том, что
сборщик мусора использует алгоритмы, чтобы решить, возвращать или нет возвращать легко достижимый объект, но всегда восстанавливает слабо достижимый объект.
SoftReference
предназначен для кешей. Когда будет обнаружено, что он WeakReference
ссылается на недоступный в противном случае объект, он сразу же будет очищен. SoftReference
можно оставить как есть. Как правило, существует некоторый алгоритм, касающийся количества свободной памяти и времени, использованного последним, чтобы определить, следует ли ее очистить. Текущий алгоритм Sun предназначен для очистки ссылки, если она не использовалась в течение стольких секунд, поскольку в куче Java есть свободные мегабайты памяти (настраивается, сервер HotSpot проверяет максимально возможную кучу, как установлено -Xmx
). SoftReference
s будет очищено до того, как OutOfMemoryError
будет брошено, если иное не достижимо.
java.lang
. Такое злоупотребление синонимами никому не приносит пользы.
Эта статья может быть очень полезна для понимания сильных, мягких, слабых и фантомных ссылок.
Чтобы дать вам резюме,
Если у вас есть только слабые ссылки на объект (без сильных ссылок), то объект будет восстановлен GC в следующем цикле GC.
Если у вас есть только мягкие ссылки на объект (без сильных ссылок), то объект будет возвращен GC только тогда, когда JVM не хватит памяти.
Таким образом, вы можете сказать, что сильные ссылки имеют максимальную силу (никогда не могут быть собраны GC)
Мягкие ссылки более эффективны, чем слабые (поскольку они могут избежать цикла GC до тех пор, пока JVM не исчерпает память)
Слабые ссылки даже менее мощны, чем мягкие ссылки (поскольку они не могут спровоцировать какой-либо цикл GC и будут исправлены, если у объекта нет другой сильной ссылки).
Ресторанная аналогия
Теперь, если вы являетесь сильным клиентом (аналог сильной рекомендации), то даже если в ресторан приходит новый клиент или что-то такое, что всегда радует, вы никогда не покинете свой стол (область памяти в куче). Официант не имеет права говорить вам (или даже просить вас) покинуть ресторан.
Если вы мягкий клиент (аналог мягкого отзыва), то, если в ресторан приходит новый клиент, официант не будет просить вас покинуть стол, если не осталось другой пустой таблицы для размещения нового клиента. (Другими словами, официант попросит вас покинуть стол только в том случае, если заходит новый клиент, и для этого нового клиента не осталось другой таблицы)
Если вы слабый клиент (аналог слабой ссылки), тогда официант по своему желанию может (в любой момент) попросить вас покинуть ресторан: P
Согласно документу , свободные WeakReferences должны быть очищены работающим GC.
Согласно документу , свободные SoftReferences должны быть очищены, прежде чем OOM выбрасывается.
Это единственная реальная разница. Все остальное не является частью договора. (Я предполагаю, что последние документы являются договорными.)
SoftReferences полезны. Кэши, чувствительные к памяти, используют SoftReferences, а не WeakReferences.
weak_ref.get()
. Когда это происходит null
, вы узнаете, что между этой продолжительностью GC запускается.
Что касается неправильного использования WeakReference, список бесконечен:
бесполезный хак для реализации softreference с приоритетом 2, такой, что вам не нужно писать его, но он не работает должным образом, потому что кеш будет очищаться при каждом запуске GC, даже если есть запасная память. См. Https://stackoverflow.com/a/3243242/632951 для фаз. (Кроме того, что если вам нужно более 2 уровней приоритета кэша? Для этого вам все равно нужна настоящая библиотека.)
паршивый хак, чтобы связать данные с объектом существующего класса, но он создает утечку памяти (OutOfMemoryError), когда ваш GC решает сделать перерыв после создания ваших слабых ссылок. Кроме того, это ужасно: лучший подход - использовать кортежи.
паршивый хак, чтобы связать данные с объектом существующего класса, где у этого класса есть смелость сделать себя не подклассифицированным, и он используется в существующем коде функции, который вам нужно вызвать. В таком случае правильное решение состоит в том, чтобы либо отредактировать класс и сделать его подклассифицированным, либо отредактировать функцию и заставить ее использовать интерфейс вместо класса, либо использовать альтернативную функцию.
equals()
это просто идентификация объекта? Мягкие ссылки там кажутся пустой тратой, потому что, как только ключевой объект перестает быть сильно доступным, никто никогда не будет искать это отображение снова.
Шесть типов состояний достижимости объектов в Java:
Для получения более подробной информации: https://www.artima.com/insidejvm/ed2/gc16.html «свернуть
Следует помнить, что объект со слабой ссылкой будет собираться только тогда, когда у него ТОЛЬКО слабые ссылки. Если в нем содержится только одна сильная ссылка, она не собирается независимо от того, сколько у нее слабых ссылок.
Чтобы дать аспект использования памяти в действии, я провел эксперимент с ссылками Strong, Soft, Weak & Phantom при большой нагрузке с тяжелыми объектами, сохранив их до конца программы. Затем следил за использованием кучи и поведением GC . Эти показатели могут варьироваться от случая к случаю, но, безусловно, дают понимание высокого уровня. Ниже приведены выводы.
Поведение кучи и GC под большой нагрузкой
Вы можете получить более подробные графики, статистику, наблюдения для этого эксперимента здесь .
WeakReference : объекты, на которые имеются только слабые ссылки, собираются при каждом цикле GC (незначительном или полном).
SoftReference : когда объекты, на которые имеются только мягкие ссылки, собираются, зависит от:
-XX: SoftRefLRUPolicyMSPerMB = N флаг (значение по умолчанию 1000, то есть 1 секунда)
Количество свободной памяти в куче.
Пример:
Тогда объект, на который ссылается только SoftReference, будет собран, если в последний раз, когда к нему обращались, было больше 10 секунд.