@AjeetGanga, Свободные слабые ссылки всегда собираются всякий раз, когда запускается сборщик мусора. См. stackoverflow.com/a/46291143/632951




Слабые ссылки собираются с нетерпением. Если сборщик мусора обнаруживает, что объект слабо достижимый (достижимый только через слабые ссылки), он очистит слабые ссылки на этот объект немедленно. Таким образом, они хороши для сохранение ссылки на объект, для которого ваша программа также хранит (сильно упоминается) какая-то "связанная информация", например, кешированная информация об отражении о классе или оболочке для объекта и т. д. Все, что не имеет смысла хранить после объекта, с которым оно связано с GC-изд. Когда слабая ссылка очищается, она ставится в очередь в ссылочная очередь, которую ваш код где-то опрашивает, и отбрасывает связанные объекты. То есть вы храните дополнительную информацию о объект, но эта информация не нужна, если объект, на который она ссылается уходит. Фактически, в определенных ситуациях вы даже можете создать подкласс WeakReference и сохранить связанную дополнительную информацию об объекте. в полях подкласса WeakReference. Еще одно типичное использование WeakReference используется вместе с Maps для хранения канонических экземпляров.
SoftReferences, с другой стороны, хороши для кеширования внешних, воссоздаемых ресурсов. поскольку GC обычно задерживает их очистку. Однако гарантируется, что все SoftReferences будут очищены перед выбросом OutOfMemoryError, поэтому они теоретически не может вызвать OOME [*].
Типичный пример использования - сохранение проанализированной формы содержимого из файл. Вы бы реализовали систему, в которой вы загружали бы файл, анализировали его и сохраняли SoftReference на корневой объект анализируемого представления. В следующий раз вам нужен файл, вы попытаетесь получить его через SoftReference. Если вы можете получить его, вы избавили себя от еще одной загрузки / синтаксического анализа, и если сборщик мусора тем временем очистил, перезагружаешь. Таким образом, вы используете бесплатно память для оптимизации производительности, но не рискуйте OOME.
Теперь о [*]. Сохранение SoftReference само по себе не может вызвать OOME. Если с другой стороны, вы по ошибке используете SoftReference для задачи, подразумевается WeakReference для использования (а именно, вы каким-то образом сохраняете информацию, связанную с объектом имеет сильную ссылку, и отбросьте ее, когда объект Reference получит очищен), вы можете запустить OOME в качестве кода, который опрашивает ReferenceQueue и отбрасывает связанные объекты, которые могут не запускаться вовремя мода.
Итак, решение зависит от использования - если вы кешируете дорогостоящую информацию, но тем не менее, реконструируемый из других данных, используйте мягкие ссылки - если вы сохраняете ссылку на канонический экземпляр некоторых данных, или вы хотите иметь ссылку на объект, не владея им (таким образом, предотвращая его сборку мусора), используйте слабую ссылку.
Особенно полезно для объяснения того, когда будут использоваться слабые объекты.
Ключевым моментом в правильном использовании WeakReference является то, что там, где его следует использовать, тот факт, что он может оставаться действительным некоторое время после того, как ссылка выходит за рамки, может быть допустимым, но нежелательным.
Я изо всех сил пытаюсь понять, в чем польза WeakHashMap, если он всегда создает слабую ссылку на свой объект ключевого значения?
@supercat, есть только один правильное использование WeakReference, которое должно наблюдать за запусками GC. См. Уточнение: stackoverflow.com/a/46291143/632951
@Pacerier: Автор этого поста просто ошибается. Он пренебрегает некоторыми другими сценариями использования, такими как подписка на события, его второй пункт бессмысленен, а его третий пункт предполагает, что программист может делать вещи, которые могут быть невозможны. Его первая мысль разумна, но напрямую связана с тем, что я сказал. Если коду часто придется создавать большие неизменяемые объекты и сравните, например, строительная часть часто будет дешевле, если код создает новые объекты без учета того, существуют ли они уже, но сравнение между объектом и самим собой (идентичные ссылки) будет. ..
... намного дешевле, чем сравнение двух разных неизменяемых объектов, содержащих одни и те же данные. Если коду требуется объект, который соответствует существующему объекту, использование ссылки на существующий объект (вместо нового) будет полезно, если эти объекты будут сравниваться. Однако, если объект существует в интернированном кэше и нигде больше, возврат ссылки на него будет дороже, чем создание нового объекта и возврат ссылки на него и не даст никаких преимуществ перед ним.
SoftReference предназначен для кешей. Когда обнаруживается, что WeakReference ссылается на другой недостижимый объект, он немедленно очищается. SoftReference можно оставить как есть. Обычно существует некоторый алгоритм, связанный с объемом свободной памяти и временем последнего использования, чтобы определить, следует ли ее очистить. Текущий алгоритм Sun состоит в том, чтобы очистить ссылку, если она не использовалась столько секунд, сколько мегабайт свободной памяти в куче Java (настраивается, сервер HotSpot проверяет максимально возможную кучу, установленную -Xmx). SoftReference будут очищены до того, как будет брошен OutOfMemoryError, если не будет достигнуто иное.
Но в Android это не рекомендуется для кешей developer.android.com/reference/java/lang/ref/…
@DoctororDrive tbf вопрос был про java, а не dalvik! :-П
@YaroslavMytkalyk, Откровенно говоря, если Android хочет переписать поведение класса, он должен использовать собственное пространство имен, а не java.lang. Такое злоупотребление синонимами никому не приносит никакой пользы.
Из Понимание слабых ссылок, от Итана Николаса:
Weak references
A weak reference, simply put, is a reference that isn't strong enough to force an object to remain in memory. Weak references allow you to leverage the garbage collector's ability to determine reachability for you, so you don't have to do it yourself. You create a weak reference like this:
WeakReference weakWidget = new WeakReference(widget);and then elsewhere in the code you can use
weakWidget.get()to get the actualWidgetobject. Of course the weak reference isn't strong enough to prevent garbage collection, so you may find (if there are no strong references to the widget) thatweakWidget.get()suddenly starts returningnull....
Soft references
A soft reference is exactly like a weak reference, except that it is less eager to throw away the object to which it refers. An object which is only weakly reachable (the strongest references to it are
WeakReferences) will be discarded at the next garbage collection cycle, but an object which is softly reachable will generally stick around for a while.
SoftReferencesaren't required to behave any differently thanWeakReferences, but in practice softly reachable objects are generally retained as long as memory is in plentiful supply. This makes them an excellent foundation for a cache, such as the image cache described above, since you can let the garbage collector worry about both how reachable the objects are (a strongly reachable object will never be removed from the cache) and how badly it needs the memory they are consuming.
И Питер Кесслер добавил в комментарии:
The Sun JRE does treat SoftReferences differently from WeakReferences. We attempt to hold on to object referenced by a SoftReference if there isn't pressure on the available memory. One detail: the policy for the "-client" and "-server" JRE's are different: the -client JRE tries to keep your footprint small by preferring to clear SoftReferences rather than expand the heap, whereas the -server JRE tries to keep your performance high by preferring to expand the heap (if possible) rather than clear SoftReferences. One size does not fit all.
Сообщение больше недоступно, вы можете найти его на машине возврата: web.archive.org/web/20061130103858/http://weblogs.java.net/b log /…
на этот раз архив больше не доступен
Единственная реальная разница между мягкой и слабой ссылкой состоит в том, что
the garbage collector uses algorithms to decide whether or not to reclaim a softly reachable object, but always reclaims a weakly reachable object.
@ATorras, Самир. Я расширил этот ответ здесь: stackoverflow.com/a/46291143/632951
Слабая ссылкаhttp://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html
Принцип:weak reference относится к сборке мусора. Обычно объект, имеющий один или несколько reference, не подлежит сборке мусора.
Вышеупомянутый принцип не применим, если это weak reference. Если объект имеет только слабую ссылку с другими объектами, он готов к сборке мусора.
Давайте посмотрим на приведенный ниже пример: У нас есть Map с объектами, где ключ ссылается на объект.
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(...).
Ваш первый пример HashMap выглядит неправильно. Когда вы выполняете "aMap.put (emp, val);" и emp, и val - сильные ссылки. Внутри создается новая переменная для хранения «emp» и «val», поэтому, когда вы выполняете «emp = null;» вы просто обнуляете переменную "emp", но не внутреннюю переменную для хэш-карты (которая все еще содержит исходный объект Employee). Следовательно, хеш-карта по-прежнему будет содержать сильную ссылку на emp, независимо от того, что вы делаете с внешней переменной emp.
@Tiago. Нет. Предположительно под «первым примером» вы имеете в виду пример 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
Выполнено 0 вызовов System.gc (), в результате чего размер weakHashMap равен: 0 - это результат вашей второй программы?
Другой пример WeakHashMap в действии, с примером приложения, показывающим, как удаляются записи, выполняется только сборка мусора после, см. мой ответ к вопросу, WeakHashMap постоянно растет или очищает ключи от мусора?.
В Java; По порядку от сильнейшего к самому слабому: Сильный, Мягкий, Слабый и Призрачный.
Сильная ссылка - это обычная ссылка, которая защищает упомянутый объект от сбора сборщиком мусора. т.е. никогда не собирает мусор.
Мягкая ссылка имеет право на сбор сборщиком мусора, но, вероятно, не будет собираться, пока его память не понадобится. т.е. мусор собирается до OutOfMemoryError.
Слабая ссылка - это ссылка, которая не защищает объект, на который указывает ссылка, от сбора сборщиком мусора. т.е. мусор собирается, когда нет сильных или мягких ссылок.
Фантомная ссылка - это ссылка на объект, на который фантомно ссылаются после того, как он был завершен, но до того, как его выделенная память будет освобождена.
Аналогия: Предположим, что 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?
да, сборщик мусора не будет собирать ссылку, пока не освободится память.
Мне нравятся простые объяснения, без лишнего бла-бла-бла +1 от меня!
Отличное резюме с новаторским примером
+1, дополнительная литература: javarevisited.blogspot.in/2014/03/…
Шесть типов состояний достижимости объектов в Java:
Подробнее: https://www.artima.com/insidejvm/ed2/gc16.html «свернуть
Плохое описание фантомных ссылок. Кроме того, вы перечислили 4 типа в особом порядке. «фантом» - это самый слабый тип, а не самый сильный. Традиционный порядок их перечисления - «сильный, мягкий, слабый, фантомный». И я понятия не имею, откуда у вас представление о том, что фантомные объекты используются для механизмов кеширования. AFAIK, это временное состояние, которое видит только сборщик мусора, а не то, с чем мог бы работать обычный программист.
@ToolmakerSteve и все остальное - извиняюсь за пару вещей: 1. неправильное объяснение фантомных ссылок в предыдущей версии моего ответа и 2. Задержка исправления ошибок. Теперь ответ улучшен за счет исправления ошибок.
Следует знать, что объект со слабыми ссылками будет собран только тогда, когда он имеет ТОЛЬКО слабые ссылки. Если у него есть хотя бы одна сильная ссылка, она не будет собрана, независимо от того, сколько у нее слабых ссылок.
Это здравый смысл ... То же самое касается softref и phantomref.
Согласно документ, свободные WeakReferences должен очищаются работающим сборщиком мусора.
Согласно документ, свободные SoftReferences должен должны быть очищены до того, как будет брошен OOM.
Это единственная реальная разница. Все остальное не является частью контракта. (Я предполагаю, что последние документы являются договорными.)
SoftReferences полезны. Кеши, чувствительные к памяти, используют SoftReferences, а не WeakReferences.
weak_ref.get(). When it's null, you learn that between this duration, the GC ran.
Что касается использования WeakReference неверный, список бесконечен:
паршивый хак для реализации softreference с приоритетом 2, так что вам не нужно писать его, все же он не работает должным образом, потому что кеш будет очищен при запуске каждый GC, даже если есть свободная память. См. https://stackoverflow.com/a/3243242/632951 для фаилов. (Кроме того, что, если вам нужно более двух уровней приоритета кеша? Для этого вам все равно понадобится настоящая библиотека.)
паршивый способ связать данные с объектом существующего класса, все же, он создает утечку памяти (OutOfMemoryError), когда ваш GC решает сделать перерыв после создания ваших слабых ссылок. Кроме того, это безобразно: лучший подход - использовать кортежи.
паршивый способ связать данные с объектом существующего класса, когда у класса хватит смелости сделать себя неклассифицированным, и он используется в существующий код функции, который вам нужно вызвать. В таком случае правильное решение - либо отредактировать класс и сделать его подклассом, либо отредактировать функцию и заставить ее использовать интерфейс вместо класса, либо использовать альтернативную функцию.
Как насчет кеша, в котором equals() ключевого типа является просто идентификатором объекта? Мягкие ссылки кажутся здесь пустой тратой, потому что, как только ключевой объект становится недоступным, никто больше никогда не будет искать это сопоставление.
Я не согласен. Используйте WeakReference, если вы никоим образом не хотите влиять на сборщик мусора (вы можете сохранить ссылку на объект, а затем проверить, существует ли она еще, без каких-либо предпочтений). Используйте SoftReference, если вы хотите повлиять на сборщик мусора, чтобы он попытался сохранить объект (т. Е. Когда вы бы предпочли, чтобы сборщик мусора сохранил его).
Хороший пример использования WeakReference - в AsyncTask Android - для сохранения экземпляра контекста. Таким образом, если контекст умирает (если активность - поворот экрана и т. д.), AsyncTask не будет иметь сильной ссылки на него, и поэтому его можно будет собрать сборщиком мусора. Проверить YouTube/…
WeakReference: объекты, на которые имеются только слабые ссылки, собираются в каждом цикле сборки мусора (второстепенном или полном).
SoftReference: когда собираются только мягкие объекты, зависит от:
-XX: флаг SoftRefLRUPolicyMSPerMB = N (значение по умолчанию - 1000, или 1 секунда)
Количество свободной памяти в куче.
Пример:
Затем объект, на который ссылается только SoftReference, будет собран, если последний раз, когда к нему обращались, больше 10 секунд.
Этот статья может быть очень полезным для понимания сильных, мягких, слабых и фантомных ссылок.
Чтобы дать вам резюме,
Если у вас есть только слабые ссылки для объекта (без сильных ссылок), то объект будет возвращен GC в следующем цикле GC.
Если у вас есть только мягкие ссылки для объекта (без сильных ссылок), то объект будет возвращен GC только тогда, когда JVM исчерпает память.
Таким образом, вы можете сказать, что сильные ссылки имеют высшая сила (никогда не могут быть собраны GC)
Мягкие ссылки - это мощный, чем слабые ссылки (поскольку они могут выйти из цикла GC, пока JVM не исчерпает память)
Слабые ссылки - это еще менее мощный, чем мягкие ссылки (поскольку они не могут исключать какой-либо цикл GC и будут восстановлены, если у объекта нет другой сильной ссылки).
Ресторанная аналогия
Теперь, если вы являетесь сильный клиент (аналогично сильной ссылке), то даже если в ресторан зайдет новый клиент или что-то подобное случится, вы никогда не покинете свой стол (область памяти в куче). Официант не имеет права сказать вам (или даже попросить) покинуть ресторан.
Если вы являетесь мягкий клиент (аналог мягкой ссылки), то, если в ресторан заходит новый клиент, официант не будет просить вас покинуть стол, если только не останется другого пустого стола для размещения нового клиента. (Другими словами, официант попросит вас покинуть столик только в том случае, если зайдет новый клиент и для этого нового клиента не останется другого стола)
Если вы слабый покупатель (аналог слабой ссылки), то официант по своему желанию может (в любой момент) попросить вас покинуть ресторан: P
Чтобы дать представление об использовании памяти в действии, я провел эксперимент с сильными, мягкими, слабыми и фантомными ссылками при большой нагрузке с тяжелыми объектами, сохраняя их до конца программы. Тогда отслеживаемое использование кучи и поведение сборщика мусора. Эти показатели могут варьироваться от случая к случаю, но, безусловно, дают понимание на высоком уровне. Ниже приведены результаты.
Поведение кучи и сборщика мусора при большой нагрузке
Вы можете получить более подробную информацию о графики, статистика, наблюдения для этого эксперимента здесь.
SoftReferences - это тип (не совсем, но для обсуждения) WeakReferences, которые обычно собираются, когда JVM считает, что не хватает памяти.