В чем разница между SoftReference и WeakReference в Java? - PullRequest
757 голосов

Ответы [ 11 ]

872 голосов
/ 18 ноября 2008

От Понимание слабых ссылок , Итан Николас:

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

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

WeakReference weakWidget = new WeakReference(widget);

, а затем в другом месте кода вы можете использовать weakWidget.get() чтобы получить фактический Widget объект. Конечно слабый ссылка не достаточно сильна, чтобы предотвратить сборку мусора, так что вы можете найти (если нет сильных ссылки на виджет), что weakWidget.get() внезапно начинается возвращение null.

...

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

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

SoftReferences не требуется до вести себя иначе, чем WeakReferences, но на практике тихо достижимые объекты, как правило, сохраняется до тех пор, пока память находится в обильный запас. Это делает их отличная основа для кеша, такая как кеш изображений, описанный выше, так как вы можете позволить мусор коллекционер беспокоиться о том, как достижимы объекты (сильно достижимый объект никогда не будет удален из кеша) и как сильно это нужно память, которую они потребляют.

И Питер Кесслер добавил в комментарии:

Sun JRE рассматривает SoftReferences иначе, чем WeakReferences. Мы пытаемся удержать объект, на который ссылается SoftReference, если нет давления на доступную память. Одна деталь: политика для JRE "-client" и "-server" различна: JRE -client старается сохранить ваш размер небольшим, предпочитая очищать SoftReferences, а не расширять кучу, тогда как JRE -server пытается сохранить высокая производительность, предпочитая расширять кучу (если возможно), а не очищать SoftReferences. Один размер не подходит для всех.

195 голосов
/ 18 ноября 2008

Слабые ссылки собираются с нетерпением. Если GC обнаружит, что объект слабодоступный (достижимый только по слабым ссылкам), он очистит слабые ссылки на этот объект сразу. Как таковые, они хороши для сохраняя ссылку на объект, для которого ваша программа также хранит (строго ссылаются) «связанная информация» была, например, кэширована отражение информации о классе или обертке для объекта и т. д. Все, что не имеет смысла оставлять после объекта, с которым оно связано с GC-ред. Когда слабая ссылка очищается, она ставится в очередь в ссылочная очередь, которую ваш код где-то опрашивает, и она отбрасывает связанные объекты. То есть вы храните дополнительную информацию о объект, но эта информация не нужна, если объект, к которому она относится уходит. На самом деле, в определенных ситуациях вы можете даже подкласс WeakReference и сохраняем связанную дополнительную информацию об объекте в полях подкласса WeakReference. Еще одно типичное использование WeakReference используется вместе с Maps для хранения канонических экземпляров.

С другой стороны, SoftReferences хороши для кэширования внешних восстанавливаемых ресурсов. поскольку GC обычно задерживает их очистку. Хотя все гарантировано SoftReferences будут очищены до того, как OutOfMemoryError брошен, поэтому они теоретически не может вызвать ООМ [*].

Типичный пример использования - сохранение проанализированной формы содержимого из файл. Вы бы внедрили систему, в которой вы загрузите файл, проанализируете его и сохраните SoftReference к корневому объекту разобранного представления. В следующий раз вам нужен файл, вы попытаетесь получить его через SoftReference. Если вы можете получить его, вы избавили себя от другой загрузки / разбора, и если GC очистил это в то же время, вы перезагрузите его. Таким образом, вы используете бесплатно память для оптимизации производительности, но не рискуйте OOME.

Теперь для [*]. Сохранение SoftReference не может вызвать OOME само по себе. Если с другой стороны, вы по ошибке используете SoftReference для выполнения задачи WeakReference для использования (а именно, вы храните информацию, связанную с объектом как-то строго ссылаться, и отказаться от него, когда объект ссылки получает очищено), вы можете запустить OOME как ваш код, который опрашивает ReferenceQueue и отбрасывает связанные объекты могут произойти не своевременно мода.

Итак, решение зависит от использования - если вы кешируете информацию, которую дорого построить, но тем не менее, восстанавливаемые из других данных, используйте мягкие ссылки - если вы храните ссылку на канонический экземпляр некоторых данных, или Вы хотите иметь ссылку на объект, не «владея» им (таким образом, чтобы он не был GC'd), используйте слабую ссылку.

124 голосов
/ 03 августа 2015

на Java ; от сильнейших до слабых: сильные, мягкие, слабые и фантомные

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

A Мягкая ссылка может собираться сборщиком мусора, но, вероятно, не будет собираться, пока не потребуется его память. то есть мусор собирается до OutOfMemoryError.

A Слабая ссылка - это ссылка, которая не защищает ссылочный объект от сбора GC. то есть мусор собирается, когда нет сильных или мягких рефсов.

A Фантомная ссылка - ссылка на объект, на которую фантомно ссылаются после того, как он был завершен, но до того, как выделенная память была освобождена.

Источник

Аналогия: Предположим, что JVM - это королевство, Object - это король королевства, а GC - атакующий королевства, который пытается убить короля (объект).

  • Когда король Сильный , GC не может убить его.
  • Когда Кинг Мягкий , GC атакует его, но Кинг правит королевством с защитой, пока ресурс не будет доступен.
  • Когда король слаб , GC атакует его, но управляет королевством без защиты.
  • Когда король Призрак , GC уже убил его, но король доступен через его душу.
70 голосов
/ 17 октября 2013

Слабая ссылка 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.

46 голосов
/ 03 апреля 2012

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

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

22 голосов
/ 18 ноября 2008

SoftReference предназначен для кэшей. Когда обнаруживается, что WeakReference ссылается на недоступный в противном случае объект, он сразу же очищается. SoftReference можно оставить как есть. Как правило, существует некоторый алгоритм, касающийся количества свободной памяти и времени, использованного последним, чтобы определить, следует ли ее очистить. Текущий алгоритм Sun предназначен для очистки ссылки, если она не использовалась в течение стольких секунд, когда в куче Java свободно мегабайт памяти (настраивается, сервер HotSpot проверяет максимально возможную кучу, установленную -Xmx). SoftReference с будет сброшено до того, как будет выброшено OutOfMemoryError, если не достигнуто иное.

7 голосов
/ 14 августа 2018

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


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

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

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


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

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

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


Ресторанный аналог

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

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

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

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

7 голосов
/ 19 сентября 2017

Единственная реальная разница

За документ , слабые слабые ссылки должен быть очищен работающим ГХ.

За документ , свободные SoftReferences должны быть очищены до выброса OOM.

Это единственная реальная разница. Все остальное не является частью договора. (Я предполагаю, что последние документы являются договорными.)

Полезные SoftReferences полезны. Кэши, чувствительные к памяти, используют SoftReferences, а не WeakReferences.


Единственное правильное использование WeakReference - это наблюдение за запуском GC. Вы делаете это, создавая новую WeakReference, чей объект немедленно выходит из области видимости, затем пытаетесь получить значение null из weak_ref.get(). Когда это null, вы узнаете, что между этой продолжительностью GC бежал.

Что касается неправильное использование WeakReference, список бесконечен:

  • паршивый хак для реализации softreference приоритета-2, так что вам не нужно писать один, пока он не работает должным образом, потому что кэш будет очищен на каждый запуск GC, даже если есть запасная память. Смотрите https://stackoverflow.com/a/3243242/632951 для фаз. (Кроме того, что если вам нужно более 2 уровней приоритета кэша? Для этого вам все равно нужна настоящая библиотека.)

  • паршивый хак, связывающий данные с объектом существующего класса, все же он создает утечку памяти (OutOfMemoryError), когда ваш ГХ решает сделать перерыв после создания ваших слабых ссылок. Кроме того, это безобразно: лучший подход - использовать кортежи.

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

3 голосов
/ 17 августа 2015

Шесть типов состояний достижимости объектов в Java -

  1. Сильные только достижимые объекты - GC не будет собирать ( восстанавливать память, занятую ) объектами такого типа. Они достижимы через корневой узел или другой сильно достижимый объект (т.е. через локальные переменные, переменные класса, переменные экземпляра и т. Д.)
  2. Мягкие легко достижимые объекты - GC может попытаться собрать этот тип объектов в зависимости от конфликта памяти. Они доступны из корня через один или несколько мягких справочных объектов
  3. Слабые только достижимые объекты - GC должен собирать такие объекты. Эти достижимы из корня через один или несколько слабых эталонных объектов
  4. Воскрешающие объекты - GC уже находится в процессе сбора этих объектов. Но они могут вернуться в одно из состояний - Сильное / Мягкое / Слабое при выполнении какого-то финализатора
  5. Фантом достижимый объект - GC уже находится в процессе сбора этих объектов и определил, что не может быть восстановлен любым финализатором (если он объявляет сам метод finalize (), тогда его финализатор будет запущен) . Они доступны из корня через один или несколько фантомных эталонных объектов
  6. Недостижимый объект - объект не является ни сильно, ни мягко, ни слабо, ни фантомно достижим, и не подлежит воскрешению. Эти объекты готовы к утилизации

Для более подробной информации: https://www.artima.com/insidejvm/ed2/gc16.html «свернуть

1 голос
/ 15 мая 2016

Следует помнить, что объект со слабой ссылкой будет собираться только тогда, когда у него ТОЛЬКО слабая ссылка (и). Если в нем содержится только одна сильная ссылка, она не собирается независимо от того, сколько у нее слабых ссылок.

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