Яка різниця між SoftReference і WeakReference в Java?


810

9
SoftReferences - це тип (не дуже, але заради обговорення) слабких референцій, які зазвичай збираються, коли JVM вважає, що це не в пам'яті.
Ajeet Ganga

5
@AjeetGanga, слабкі слабкі рефлекси завжди збираються, коли працює GC. Див stackoverflow.com/a/46291143/632951
Pacerier

Відповіді:


926

Із розуміння слабких посилань , Етан Ніколас:

Слабкі посилання

Простий посилання , простіше кажучи, - це посилання, яке недостатньо сильне, щоб змусити об'єкт залишитися в пам'яті. Слабкі посилання дозволяють використовувати можливості сміттєзбірника визначати доступність для вас, тому вам не доведеться робити це самостійно. Ви створюєте такий слабкий посилання:

WeakReference weakWidget = new WeakReference(widget);

а потім в іншому місці коду, який ви можете використовувати weakWidget.get()для отримання фактичного Widgetоб'єкта. Звичайно, слабка посилання недостатньо сильна, щоб запобігти вивезенню сміття, тому ви можете виявити (якщо немає чітких посилань на віджет), що weakWidget.get()раптом починає повертатися null.

...

М'які посилання

М'яка посилання точно як слабка посилання, за винятком того, що він менш прагне викинути об'єкт , до якого воно відноситься. Об'єкт, який є слабкодоступним (найсильніші посилання на нього WeakReferences), буде відкинутий у наступному циклі вивезення сміття, але об'єкт, який буде легко доступний, як правило, на деякий час буде триматися навколо.

SoftReferencesвід них не потрібно поводитись інакше, ніж WeakReferencesна практиці, м'якодоступні об'єкти, як правило, зберігаються до тих пір, поки пам’ять не вистачає. Це робить їх відмінною основою для кешу, наприклад кеш зображень, описаний вище, оскільки ви можете дозволити колектору сміття турбуватися як про доступність об'єктів (сильнодоступний об'єкт ніколи не буде видалений з кеша), так і наскільки це погано потрібна пам'ять, яку вони споживають.

А Пітер Кесслер додав у коментарі:

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


7
Чи не повідомлення більше не доступний, ви можете знайти його на Вайбак машини: web.archive.org/web/20061130103858/http: //weblogs.java.net/blog / ...
riccardo.tasso

цього разу архів більше не доступний
user1506104

209

Слабкі посилання збираються охоче. Якщо GC виявить, що об'єкт є слабодоступним (він доступний лише через слабкі посилання), він негайно очистить слабкі посилання на цей об’єкт. Таким чином, вони хороші для збереження посилання на об'єкт, на який ваша програма також зберігає (сильно посилається) "пов’язану інформацію", як-от інформація про кешоване відображення про клас або обгортку для об'єкта тощо. Все, що робить немає сенсу триматись після об'єкта, з яким він асоціюється, є GC-ed. Коли слабка посилання очищається, вона вмикається в черзі посилань, що ваш код десь опитується, і він також відкидає пов'язані об'єкти. Тобто ви зберігаєте додаткову інформацію про об’єкт, але ця інформація не потрібна, як тільки об’єкт, на який вона посилається, відходить. Насправді, у певних ситуаціях ви навіть можете підкласифікувати WeakReference та зберігати пов'язану додаткову інформацію про об’єкт у полях підкласу WeakReference. Ще одне типове використання WeakReference - це спільно з Maps для зберігання канонічних екземплярів.

З іншого боку, SoftReferences хороші для кешування зовнішніх рекреаційних ресурсів, оскільки GC зазвичай затримує їх очищення. Хоча гарантується, що всі SoftReferences будуть очищені до того, як OutOfMemoryError буде викинутий, тому вони теоретично не можуть спричинити OOME [*]

Типовим прикладом використання є збереження розібраної форми вмісту з файлу. Ви б застосували систему, де ви завантажуєте файл, розбираєте його та зберігаєте SoftReference до кореневого об'єкта проаналізованого подання. Наступного разу, коли вам потрібен файл, ви спробуєте отримати його через SoftReference. Якщо ви можете отримати його, ви шкодуєте собі ще одне завантаження / розбір, і якщо GC тим часом очистив його, ви перезавантажите його. Таким чином, ви використовуєте вільну пам’ять для оптимізації продуктивності, але не ризикуйте НАДОМОГО.

Тепер для [*]. Збереження SoftReference не може спричинити за собою OOME. Якщо, з іншого боку, ви помилково використовуєте SoftReference для завдання, яке має на увазі використовувати WeakReference (а саме ви зберігаєте інформацію, пов’язану з Об'єктом якось сильно посилається, і відкидаєте її, коли очищається об'єкт Reference), ви можете зіткнутися з OOME як ваш код, який опитує чергу ReferenceQue і відкидає пов'язані об'єкти, може статися таким, що не працює своєчасно.

Отже, рішення залежить від використання - якщо ви кешуєте інформацію, яку дорого будувати, але все-таки реконструювати з інших даних, використовуйте м'які посилання - якщо ви зберігаєте посилання на канонічний примірник деяких даних, або ви хочете мати посилання на об’єкт, не "володіючи ним" (таким чином, не дозволяючи йому бути GC'd), використовувати слабке посилання.


14
Особливо корисно для пояснення, коли слабкі предмети будуть використовуватися.
Джек БеНімбл

Ключовим моментом щодо правильного використання атрибутів WeakReferenceє те, що в місцях, де слід його використовувати, той факт, що він може залишатись дійсним ще деякий час після того, як посилання вийде за межі сфери, може бути допустимим, але небажаним.
supercat

Я намагаюся зрозуміти, в чому полягає користь WeakHashMap, якщо він завжди дає слабке посилання на його ключовий ціннісний об'єкт?

@supercat, Існує лише одне правильне використання, WeakReferenceяке полягає в спостереженні запусками GC. Див розробки: stackoverflow.com/a/46291143/632951
Pacerier

1
@Pacerier: Автор цієї публікації просто помиляється. Він нехтує деякими іншими сценаріями використання, такими як підписка на події, його другий пункт є безглуздим, а його третій пункт передбачає, що програміст може робити те, що може бути неможливим. Його перший пункт розумний, але безпосередньо пов'язаний з тим, що я сказав. Якщо для коду часто доведеться будувати та порівнювати великі незмінні об'єкти, наприклад, будівельна частина часто буде дешевшою, якщо код створює нові об'єкти, не зважаючи на те, чи вони вже існують, але порівняння між об'єктом і самим собою (однакові посилання) буде ...
supercat

155

На Яві ; порядку від найсильнішого до найслабшого, є: Сильний, М'який, Слабкий і Фантомний

Сильна посилання нормальна посилання , яка захищає згаданий об'єкт з колекції з допомогою ОГО. тобто ніколи сміття не збирає.

М'яка посилання має право для збору збирача сміття, але , ймовірно , не збиратиметься , поки його пам'ять не потрібно. тобто сміття збирає раніше OutOfMemoryError.

Слабка посилання є посиланням , що не захищає об'єкт , на який посилається з колекції з допомогою ГХ. тобто сміття збирається, коли немає сильних або м'яких посилань.

Фантом посилання є посилання на об'єкт phantomly посилається після того, як вона була завершена, але до його виділена пам'ять була утилізована.

Джерело

Аналогія: Припустимо, що JVM - це королівство, Об'єкт - цар королівства, а GC - це нападник королівства, який намагається вбити царя (об'єкт).

  • Коли Король сильний , GC не може його вбити.
  • Коли King є м'яким , GC атакує його, але King управляє королівством із захистом, поки ресурси не будуть доступні.
  • Коли король слабкий , GC атакує його, але править королівством без захисту.
  • Коли король є Phantom , GC вже вбив його, але король доступний через його душу.

7
М'яке посилання ... 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?
ToolmakerSteve

1
так, сміттєзбірник не збиратиме посилання, поки не буде доступна пам'ять.
Премрай,

2
Мені подобаються прості пояснені речі, без занадто багато бла-бла-1 від мене!
Аделін

3
Відмінна резюме з інноваційним прикладом
Равіндра бабу

+1, подальше читання: javarevisited.blogspot.in/2014/03/…
roottraveller

77

Слабка довідка http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html

Принцип: weak reference пов'язаний зі збиранням сміття. Зазвичай об’єкти, які мають одну або більше reference, не можуть брати участь у вивезенні сміття.
Вищезазначений принцип не застосовується, коли він є weak reference. Якщо об’єкт має лише слабке посилання на інші об'єкти, то його готові до вивезення сміття.

Розглянемо нижченаведений приклад: у нас є Mapоб'єкти, де 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це той, де записи ( 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. Цього можна уникнути, загорнувши об’єкт у слабку референцію .

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.


5
Ви можете отримати NullPointerExceptionпо прибуттю aMap.get().put(...).
xehpuk

Ваш перший приклад HashMap виглядає неправильно. Коли ви робите "aMap.put (emp, val);" і 'emp', і 'val' є важливими посиланнями. Внутрішньо створена нова змінна для утримування 'emp' і 'val', тому коли ви робите "emp = null;" ви просто зводите до змінну "emp", але не зміну внутрішньо на хеш-карту (яка все ще містить оригінальний об'єкт Employee). Тому хеш-карта все ще буде чітко посилатися на 'emp' незалежно від того, що ви робите зі змінною 'emp' зовні.
Тіаго

@Tiago. Ні. Імовірно, "першим прикладом" ви посилаєтесь на WeakHashMapприклад (оскільки це перший, який демонструє слабку поведінку). Подивіться на doc для "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
ToolmakerSteve

Ви зробили 0 дзвінків на System.gc (), щоб призвести до слабкого розміру HashMap: 0 - це вихід вашої другої програми?
Аделін

1
Ще один приклад WeakHashMapдії, наприклад, додаток, який показує, як видаляються записи лише після виконання сміття, дивіться мій відповідь на запитання, чи слабко зростає WeakHashMap чи чи видаляються ключі від сміття? .
Василь Бурк

50

Єдина реальна різниця між м'якою посиланням і слабкою посиланням полягає в тому, що

сміттєзбірник використовує алгоритми, щоб вирішити, повернути чи ні повернути м'якодоступний об'єкт, але завжди відновлює слабкодоступний об'єкт.


@ATorras, Самір. Я розширив цю відповідь тут: stackoverflow.com/a/46291143/632951
Pacerier

25

SoftReferenceпризначений для схованок. Коли буде встановлено, що WeakReferenceпосилається на інакше недоступний об'єкт, він буде видалений негайно. SoftReferenceможе залишитися як є. Зазвичай існує певний алгоритм, що стосується обсягу вільної пам'яті та часу, який останній використовується, щоб визначити, чи слід його очистити. Поточний алгоритм Sun полягає в тому, щоб очистити посилання, якщо він не використовувався протягом стількох секунд, оскільки на купі Java є мегабайти пам'яті, що не вільна (налаштовується, сервер HotSpot перевіряє максимальну можливу купу, встановлену -Xmx). SoftReferences буде очищено, перш ніж OutOfMemoryErrorбуде кинуто, якщо інше не буде доступно.


9
Але в Android це не рекомендується для кешів developer.android.com/reference/java/lang/ref/…
Ярослав Миткалик

4
@DoctororDrive tbf питання стосувалося java, а не дальвіка! :-P
fabspro

2
@YaroslavMytkalyk, Чесно кажучи, якщо Android хоче переписати поведінку класу, він повинен використовувати власний простір імен, а не java.lang. Таке зловживання синонімами нікому не приносить користі.
Pacerier

9

Ця стаття може бути дуже корисною для розуміння сильних, м'яких, слабких та фантомних посилань.


Щоб дати вам підсумок,

Якщо у вас є лише слабкі посилання на об'єкт (без чітких посилань), GC об'єкт буде відтворений в наступному циклі GC.

Якщо у вас є лише м'які посилання на об'єкт (без чітких посилань), GC об'єкт буде відтворений лише тоді, коли у JVM не вистачає пам'яті.


Отже, ви можете сказати, що потужні посилання мають вищу силу (ніколи не може бути зібрана GC)

М'які посилання є потужними, ніж слабкі посилання (оскільки вони можуть уникнути циклу GC, поки у JVM не закінчиться пам'ять)

Слабкі посилання є навіть менш потужними, ніж м'які посилання (оскільки вони не можуть уникнути жодного циклу GC і будуть відтворені, якщо об'єкт не має інших сильних посилань).


Аналогія ресторану

  • Офіціант - GC
  • Ви - Об'єкт у купі
  • Зона / простір ресторану - Купольний простір
  • Новий клієнт - новий об’єкт, який хоче стіл у ресторані

Тепер, якщо ви є надійним клієнтом (аналогічним сильним посиланням), то навіть якщо в ресторан завітає новий клієнт або він так радує, ви ніколи не покинете свій стіл (область пам'яті на купі). Офіціант не має права сказати вам (або навіть просити вас) покинути ресторан.

Якщо ви м'який замовник (аналог м'яких посилань), то, якщо в ресторан приходить новий клієнт, офіціант не попросить вас покинути стіл, якщо не залишиться іншого порожнього столу для розміщення нового клієнта. (Іншими словами, офіціант попросить вас залишити стіл лише у тому випадку, якщо новий клієнт вступив, а для цього нового клієнта не залишилося іншої таблиці)

Якщо ви слабкий клієнт (аналогічний слабкому посиланню), то офіціант за його бажанням може (у будь-який момент часу) попросити вас покинути ресторан: P


7

Єдина реальна різниця

Відповідно до документа , вільні WeakReferences повинні бути очищені за допомогою GC.

Відповідно до документа , звільнені SoftReferences повинні бути очищені до викиду OOM.

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

SoftReferences корисні. В кеш-пам'яті кеш-пам'яті використовують SoftReferences, а не WeakReferences.


Єдине правильне використання WeakReference - це спостереження за запуском GC. Ви робите це, створюючи нову WeakReference, об’єкт якої негайно виходить з рамки, а потім спробуйте вийти з нуля weak_ref.get(). Коли nullви дізнаєтесь, що між цією тривалістю GC пробігав.

Що стосується неправильного використання WeakReference, то список нескінченний:

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

  • невдалий хак для асоціації даних з об'єктом існуючого класу, але він створює витік пам'яті (OutOfMemoryError), коли ваш GC вирішить зробити перерву після створення ваших слабких налаштувань. Окрім того, це не надто потворно: кращим підходом є використання кортежів.

  • паршивий хак для асоціації даних з об'єктом існуючого класу, де клас має нерв, щоб зробити себе некласифікованим, і використовується у існуючому коді функції, який потрібно викликати. У такому випадку правильним рішенням є або відредагувати клас, і зробити його підкласовим, або відредагувати функцію і змусити її взяти інтерфейс замість класу, або використовувати альтернативну функцію.


А що з кешем, де ключовим типом equals()є лише ідентичність об'єкта? М'які посилання там здаються марними, тому що, як тільки ключовий об’єкт вже не може бути доступний, ніхто більше не буде шукати це відображення знову.
HighCommander4

Я не погоджуюсь. Використовуйте WeakReference, коли ви жодним чином не хочете впливати на GC (ви можете зберегти посилання на об'єкт, а потім перевірити, чи він все ще існує, без будь-яких уподобань). Використовуйте SoftReference, якщо ви хочете впливати на GC, щоб спробувати зберегти об'єкт (тобто коли ви хочете, щоб GC зберігав його).
Девід Рефаелі

Хороший приклад, де використовувати WeakReference, є в Android AsyncTask - щоб зберегти екземпляр контексту. Таким чином, якщо контекст відмирає (якщо активність - обертання екрана тощо), AsyncTask не матиме жодних чітких посилань на нього, і тому він може збирати сміття. Перевірте youtu.be/…
Девід Рефаелі

3

Шість типів стану об'єктної доступності на Java:

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

Детальніше: https://www.artima.com/insidejvm/ed2/gc16.html «крах


4
Недобра характеристика фантомних посилань. Крім того, ви перерахували 4 типи у своєрідному порядку. "фантом" - це найслабший тип, а не найсильніший тип. Традиційний порядок їх переліку - "сильний, м'який, слабкий, фантомний". І я поняття не маю, звідки ви зрозуміли, що фантомні об'єкти використовуються для кешування механізмів. AFAIK, вони є тимчасовим станом, який бачить тільки GC, а не те, з чим працював звичайний програміст.
ToolmakerSteve

@ToolmakerSteve та все - Вибачення за пару речей 1. неправильне пояснення посилань Phantom у попередній версії моєї відповіді та 2. Затримка виправлення помилок. Тепер відповідь було покращено шляхом виправлення помилок
В.Відясагар

1

Слід пам’ятати, що слабо посилається об’єкт збирається лише тоді, коли він має ТІЛЬКИ слабкі посилання. Якщо у нього стільки одного сильного посилання, він не збирається незалежно від того, скільки слабких посилань у нього є.


Це здоровий глузд ... те ж саме стосується і softref і phantomref.
Pacerier

1

Щоб надати аспект використання пам’яті в дії, я провів експеримент із посиланнями Strong, Soft, слабкі та Phantom під великим навантаженням з важкими предметами, зберігаючи їх до кінця програми. Потім проводили моніторинг використання купи та поведінку GC . Ці показники можуть залежати від конкретних випадків, але, безумовно, дають високе розуміння. Нижче наведені результати.

Поводження Heap & GC при сильному навантаженні

  • Сильний / жорсткий довідник - Поки програма продовжувалася, JVM не міг зібрати збережений сильний посилальний об'єкт. Врешті-решт потрапив у "java.lang.OutOfMemoryError: Куповий простір Java"
  • Програмне забезпечення - Продовження програми використання купи постійно зростало, але старий GC GC траплявся, він наближався до максимуму. GC стартував трохи пізніше, після запуску програми.
  • Слабка довідка - Починаючи програму, об’єкти почали доопрацьовуватися та збиратися майже відразу. Здебільшого об’єкти збираються під час збирання сміття молодого покоління.
  • Phantom Reference - Подібно слабким посиланням, об'єкти, на які посилаються фантоми, також почали опрацьовуватись та збирати сміття негайно. Не було GC старого покоління, і всі об'єкти збирали у самому збиранні сміття молодого покоління.

Ви можете отримати більш детальні графіки, статистику та спостереження за цим експериментом тут .


0

Слабка референція : об'єкти, на які посилаються лише слабкі посилання, збираються на кожному циклі GC (незначний або повний).

SoftReference : коли збираються об'єкти, на які є лише м'які посилання, залежить від:

  1. -XX: SoftRefLRUPolicyMSPerMB = N прапор (значення за замовчуванням 1000, aka 1 секунда)

  2. Кількість вільної пам'яті в купі.

    Приклад:

    • купа має 10 МБ вільного місця (після повного ГК);
    • -XX: SoftRefLRUPolicyMSPerMB = 1000

    Тоді об’єкт, на який посилається лише SoftReference, буде зібраний, якщо останній раз, коли до нього звертався, перевищує 10 секунд.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.