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

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

12 ответов


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

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

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

WeakReference weakWidget = new WeakReference(widget);

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


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

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

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

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

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


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

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

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

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

на Phantom reference ссылка на объект phantomly ссылается после того, как он был завершен, но до того, как его выделенная память была восстановлена.

источник

аналогия: предположим, что 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. The 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). SoftReferences будет очищен до OutOfMemoryError выбрасывается, если иное не достижимо.


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

Per док, свободные WeakReferences должны очищается запущенным GC.

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

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

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


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

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

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

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

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


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

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

дополнительные сведения: https://www.artima.com/insidejvm/ed2/gc16.html " развал


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

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

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

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


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

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


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

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

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


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

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

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


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

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

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


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

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

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

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

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


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


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

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

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

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

    пример:

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

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