Java: різниця між сильним / м'яким / слабким / фантомним посиланням


179

Я прочитав цю статтю про цю тему, але я не дуже її розумію. Будь ласка, дайте мені поради та приклади при описі понять.



4
Я прочитав цей документ, він не допомагає мені уявити, яка різниця. (можливо, тому, що це важко прочитаний документ)

14
Якщо ви читаєте цю статтю і досі не розумієте, чи є у вас конкретні запитання щодо неї? Важко відповісти на "будь-ласка, поясніть мені Фоо", "ось що це означає", "я цього не розумію" без конкретної інформації про те, які деталі ви не отримаєте.
yshavit


@LouisWasserman Верхня посилання більше не діє.
Меджрай Малик

Відповіді:


142

Java надає два різні типи / класи опорних об'єктів : сильний і слабкий . Слабкі довідкові об'єкти можна далі розділити на м'які та фантомні .

  • Сильний
  • Слабкий
    • м’який
    • фантом

Перейдемо по пункту.

Сильний довідковий об’єкт

StringBuilder builder = new StringBuilder();

Це тип / клас еталонного об'єкта за замовчуванням, якщо не вказано інакше: builderє сильним еталонним об'єктом. Цей вид посилання робить посилається об'єкт непридатним до GC. Тобто, кожного разу, коли на об'єкт посилається ланцюг сильних довідкових об'єктів , він не може бути зібраний сміттям.

Слабкий довідковий об’єкт

WeakReference<StringBuilder> weakBuilder = new WeakReference<StringBuilder>(builder);

Слабкі довідкові об'єкти не є типовим типом / класом опорного об’єкта, і для їх використання вони повинні бути чітко вказані, як у вищенаведеному прикладі. Цей вид посилання робить опорний об'єкт придатним до GC. Тобто, якщо єдиною опорною досяжністю для StringBuilderоб'єкта в пам'яті є, власне, слабка посилання, тоді ГК дозволяється сміття збирати StringBuilderоб’єкт. Коли об'єкт в пам'яті є доступним лише слабким опорним об'єктам, він автоматично підходить до GC.

Рівні слабкості

Можна зарахувати два різних рівня слабкості: м'який і фантомний .

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

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

Слабкі довідкові об’єкти ідеально підходять для реалізації модулів кешу. Насправді, своєрідне автоматичне виселення може бути реалізовано, дозволяючи GC очищати області пам’яті, коли об’єкти / значення більше не доступні за допомогою сильних ланцюжків посилань. Прикладом є слабкі клавіші WeakHashMap .


76

Слабка довідка:

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

Посилання:

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

Посилання на фантом:

Посилання на фантоми зовсім інші, ніж SoftReference або WeakReference. Його зчеплення з об'єктом настільки немічне, що ви навіть не можете отримати об'єкт - його метод get () завжди повертається до нуля. Єдине використання для такої посилання - це відстеження, коли воно потрапляє в ReferenceQueue, оскільки в цей момент ви знаєте, що об'єкт, на який він вказував, мертвий.

Цей текст було вилучено з: https://weblogs.java.net/blog/2006/05/04/understanding-weak-references


1
Хоча все в цій відповіді виглядає правильно, мені також здається, що на пов’язаній веб-сторінці може виникнути помилка. Javadoc для пакета java.lang.ref і що для PhantomReference припустити , що об'єкт не сміття не збирає до тих пір , після того, як вона вже не «фантомної досяжні», маючи на увазі , що ( в відміну від SoftReference) а PhantomReference повинна бути видалена з черги до об'єкта він відноситься до банку бути зібраним сміттям ... і його заповнення не означає, що пов'язана пам'ять була звільнена.
Теодор Мердок

2
Натомість, я б швидше жив у світі, де ця публікація блогу є правильною.
Теодор Мердок

1
@TheodoreMurdock Явадок правильний. Фантомне посилання взагалі не перешкоджає вивезенню сміття. Після об'єднання об'єкта він не може бути збережений навіть фіналізатором, оскільки фіналізатори вже запущені. Він мертвий, але ще не пішов.
Леліель

@Leliel На насправді, посилання фантомний робить насправді збір сміття заважає після його поміщений ... Я зрозумів , що це недавно , коли помилка викликана очищає нитку до виходу рано. Наявність фантомних посилань було достатньою для того, щоб кожен посилається на фантом об'єкт зберігався у моєму відвалі, не доступний для збору ... якщо ви не обробляєте чергу, або не робите привідну фантомну довідку для gc при обробці черги ( і не очистіть () фантомну посилання), тоді ваша витік пам'яті буде включати як посилання на фантом, так і на посилається об'єкт.
Теодор Мердок

25

Проста різниця між ними SoftReferenceі WeakReferenceнадається розробником Android .

Різниця між a SoftReferenceі a WeakReference- це момент часу, коли приймається рішення про очищення та запозичення посилання:

  • A SoftReferenceслід очистити та зафіксувати його якомога пізніше, тобто у випадку, якщо ВМ загрожує втратою пам’яті.

  • А WeakReferenceможе бути ліквідований і започаткований, як тільки відомо, що він має слабкі посилання.


16

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

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

М'яке посилання :: Його більш-менш схоже на слабке посилання. Але ви можете сказати, що він тримає об’єкт трохи сильніше, ніж слабке посилання від збору сміття.

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

Сильна довідка :: Її якраз протилежний до двох вищезгаданих посилань. Вони менш люблять збирати сміття (здебільшого їх ніколи не збирають).

Для отримання додаткової інформації ви можете посилатися на наступне посилання:

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/Reference.html


3
Я думаю, що це неправильно - "Якщо збирачі сміття збирають слабку орієнтацію в першому життєвому циклі, він збиратиме м'які посилання в наступному циклі збору сміття". Це не обов'язково так, як ви можете бути впевнені, що вони виникають при послідовній роботі GC? GC може дозволити живим м'яким об'єктам жити навіть у другому та третьому виконанні. Немає документації для цього, якщо є, то, будь ласка, вкажіть посилання із зазначенням.
Саурабх Патіл

2
Крім того, ваша відповідь трохи розпливчаста, подивіться на це речення "Його більш-менш схоже на слабке посилання. Але ви можете сказати, що він тримає об’єкт трохи сильніше, ніж слабке посилання від збору сміття. ' - він чітко запитує про різницю, а не про подібність, усі ці слова додають темі більше плутанини, ніж ясності.
Саурабх Патіл

@SaurabhPatil - пропустив ваш коментар. Ось відповіді. 1. "він чітко запитує про різницю, а не про подібність" - Зверніться до опису питання (а не "лише" заголовку) "Будь ласка, дайте мені поради, і, будь ласка, дайте мені якийсь приклад для опису". 2. "Але ви можете сказати, що він тримає об'єкт трохи більше ...." Я думаю, що SOF дає можливість перемогтись і дати нові відповіді теж.
Сабія

14

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


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

Якщо у вас є чітка довідка на об'єкт, GC (Garbage Collector) ніколи не може бути зібраний / відшкодований.

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

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

Ми створюємо фантомні посилання на об’єкт, щоб відстежувати, коли об’єкт потрапляє в ReferenceQueue. Коли ви знаєте, що ви можете виконати дрібнозернисту доопрацювання (Це врятувало б вас від випадкового відродження об'єкта, оскільки фантомна довідка не дає вам реферату). Я б запропонував вам прочитати цю статтю, щоб отримати детальну інформацію про це.


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

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

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


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

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

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

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

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


10

4 ступінь відліку - Strong, Weak, Soft, Phantom

Сильний - це вид посилання, який робить посилається об'єкт непридатним до GC. класи будівельників. наприклад - StringBuilder

Слабкий - це довідка, яка підходить для GC.

Soft - це вид посилання, об'єкт якого підходить для GC, поки не буде доступна пам'ять. Найкраще для кешу зображень. Він буде тримати їх, поки не буде доступна пам'ять.

Phantom - це різновид посилання, об’єкт якого безпосередньо відповідає ГК. Використовується лише для того, щоб знати, коли об’єкт вилучається з пам'яті.

використовує:

  1. Дозволяє ідентифікувати, коли об’єкт точно видалений із пам'яті.

  2. коли finalize()метод перевантажений, GC може не статися вчасно для об'єктів, що відповідають вимогам GC, двох класів. Тож посилання на фантоми робить їх прийнятними до GC раніше finalize(), тому ви можете отримати OutOfMemoryErrors навіть тоді, коли більша частина купи сміття.

Слабкі посилання ідеально підходять для реалізації модулів кешу.


10

Сильні посилання

Це ваші звичайні посилання на об'єкти, які ми кодуємо щодня:

Employee emp = new Employee();

Змінна “emp” має чітке посилання на об’єкт Employee, а об’єкти, доступні через будь-яку ланцюжок чітких посилань, не підлягають збору сміття. Зазвичай це те, що ви хочете, але не завжди. Тепер припустимо, що ми збираємо багато співробітників з бази даних у колекції чи карті, і нам потрібно регулярно проводити багато обробки, тому для збереження продуктивності ми збережемо їх у кеші.

Наскільки це добре, але зараз нам потрібні різні дані, і нам не потрібні ці об'єкти Співробітника, і на них не посилаються ніде, крім кешу. Що спричиняє витік пам’яті, оскільки ці об’єкти не використовуються, але все ще не мають права на збір сміття, і ми не можемо вилучити ці об’єкти з кешу, оскільки ми не маємо на них посилання? Тому тут або нам потрібно спорожнити весь кеш вручну, що втомлює, або ми могли використовувати інші посилання, наприклад, слабкі посилання.

Слабка література

Слабка посилання не закріплює об'єкт у пам'яті і буде GC'd у наступному циклі GC, якщо не посилається на інші посилання. Ми можемо використовувати клас WeakReference, який надає Java, для створення кешів вище виду, які не зберігатимуть об'єкти, на які не посилаються з іншого місця.

WeakReference<Cache> cache = new WeakReference<Cache>(data);

Для доступу до даних вам потрібно зателефонувати cache.get (). Цей виклик отримати може повернути нуль, якщо слабке посилання було зібрано сміття: ви повинні перевірити повернене значення, щоб уникнути NPE. Java надає колекції, які використовують слабкі посилання, наприклад, клас WeakHashMap зберігає ключі (а не значення) як слабкі посилання. Якщо ключ - GC'd, значення автоматично також буде видалено з карти.

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

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

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

Фантомні посилання

Посилання на фантоми є найслабшими з усіх типів посилань, дзвінки на них завжди повертатимуться в нулеві. На об'єкт посилається фантомно після його остаточного завершення, але перед тим, як виділена пам'ять була відтворена, на відміну від слабких посилань, які запускаються до їх завершення, або посилання GC'd Phantom рідко використовуються.

То чим вони корисні? Коли ви будуєте посилання на фантом, ви завжди повинні проходити в черзі ReferenceQue. Це вказує на те, що ви можете використовувати фантомну посилання, щоб побачити, коли ваш об’єкт є GC'd.

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

Ви можете прочитати більше в моїй статті Типи посилань на Java (Сильна, М'яка, Слабка, Фантомна) .


Ви писали про те, що слабкі рефлексії будуть GC'ed у наступному циклі, якщо не відкликання від інших референцій ... але чи не повинно траплятися те ж саме, що і з сильними рефференціями? якщо до рефрендного режиму жодним чином не звертається, тоді він очищається ... тоді, якщо так, то де знову різниця ...? #confused
filemonczyk

1
Якщо до об'єкта звертаються, скажімо, s1 (сильний) та s2 (сильний), об'єкт не буде придатний до вивезення сміття, поки не будуть відменені і s1 і s2, але якщо об'єкт буде передано з s1 (слабкий) та s2 ( Сильний), тоді об'єкт буде придатний для вивезення сміття в наступному циклі GC, коли він буде відмежований лише від s2, оскільки s1 є слабкою посиланням, а якщо об'єкт не має ніяких інших посилань, окрім слабкого, він підходить для GC
Naresh Joshi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.