В чем разница между SoftReference и WeakReference в Java?


какая разница?   

12 703

12 ответов:

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

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

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

WeakReference weakWidget = new WeakReference(widget);

и затем в другом месте кода Вы можете использовать weakWidget.get() чтобы получить фактическое

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

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

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

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

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

В Java; порядок от самого сильного к самому слабому, есть: сильный, мягкий, слабый и Фантом

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

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

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

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

источник

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

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

Слабые Ссылки 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 of: 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.

единственное реальное различие между мягкой ссылкой и слабой ссылкой заключается в том, что сборщик мусора uses algorithms to decide whether or not to reclaim a softly reachable object, but always reclaims a weakly reachable object.

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

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

на док, свободные WeakReferences должны разрешение запуска ГХ.

на док, свободные SoftReferences должны очистится до того, как будет брошен OOM.

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

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


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

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

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

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

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

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

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

для более подробной информации:https://www.artima.com/insidejvm/ed2/gc16.html " коллапс

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

когда есть одна или несколько ссылок на объект, это не будет мусор, собранный в Java. Но это правило зависит от типа ссылки. Если объект имеет только слабую ссылку, связанную с другими объектами, то он является допустимым кандидатом для сборки мусора.

давайте возьмем пример сценария, чтобы понять его лучше. Пусть TextView будет объектом (недавно программирование в Android и так используя свой класс например :-)) и у нас будет программа генерирует идентификаторы, используемые для ее идентификации. Эти идентификаторы используются в некоторых других объектах для ссылки на текстовые представления.

...
Map textViewIdMap = new HashMap();
textViewIdMap.put(textView1, iD1);
textViewIdMap.put(textView2, iD2)
...


ключ-объект TextView, а значение-идентификатор. Теперь, во время выполнения программы мы удалили объект TextView скажем textView1. Нам не требуется этот объект представления, поэтому мы сделали его нулевым. Теперь, что произойдет с парой ключ-значение (textView1, iD1), хранящейся в HashMap. Эта пара на данный момент не имеет смысла и не требуется поскольку сам textview равен нулю.

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


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

мягкая ссылка немного сильнее, чем слабая ссылка. Мягкая ссылка позволяет для мусора сбор, но просит сборщик мусора очистить его только в том случае, если нет другого варианта. То есть он имеет право на сборку мусора, но сборщик мусора может удалить его на основе хруста памяти, который он имеет. Если у него осталось мало памяти, и он может восстановить память, то он будет собирать мягкие ссылки.

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


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

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

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


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

мягкие ссылки мощный чем слабые ссылки (так как они могут избежать цикла GC, пока JVM не закончится память)

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


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

  • официант-GC
  • Вы - объект в куче
  • ресторанная зона/пространство - пространство "кучи"
  • новый клиент-новый объект, который хочет стол в ресторане

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

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

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

следует знать, что слабо ссылочный объект будет собираться только тогда, когда он имеет только слабые ссылки. Если у него есть хотя бы одна сильная Ссылка, он не собирается независимо от того, сколько у него слабых ссылок.

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

SoftReference: когда объекты, на которые только мягко ссылаются, собираются, зависит от:

  1. - XX: SoftRefLRUPolicyMSPerMB=N флаг (значение по умолчанию 1000, ака 1 секунда)

  2. объем свободной памяти в куче.

    пример:

    • куча имеет 10 МБ свободного места (после полного GC);
    • - XX: SoftRefLRUPolicyMSPerMB=1000

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