Почему в Java есть 4 разных типа ссылок?

До сегодняшнего дня я не знал, что в Java есть четыре основных типа ссылок.

  1. Сильная ссылка : тип ссылки по умолчанию, который использует Java.
  2. Слабая ссылка . Если объект имеет слабую ссылку, GC освобождает память этого объекта при следующем запуске, даже если памяти достаточно.
  3. Мягкая ссылка . Если объект имеет мягкую ссылку, то GC освобождает память этого объекта только тогда, когда ему очень не хватает памяти.
  4. Фантомная ссылка. Если у объекта есть фиктивная ссылка, он подходит для сборки мусора. Но перед сборкой мусора JVM помещает объекты, которые должны быть удалены сборщиком мусора, в очередь с именем reference queue.

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

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

class User 
{ 
    public User info() 
    { 
        System.out.println("Info method invoked from User class");
        return null;
    }   
} 

public class ReferencesExample 
{ 
    public static void main(String[] args) 
    { 
        //Strong Reference
        User userRefObj = new User(); 
        System.out.println("1 :" + userRefObj.info());

        // Weak Reference
        WeakReference<User> weakref = new WeakReference<User>(userRefObj.info());  
        System.out.println("2 : " + weakref);

        // Soft Reference    
        SoftReference<User> softref = new SoftReference<User>(userRefObj.info());  
        System.out.println("3 : " + softref);

        // Phantom Reference 
        ReferenceQueue<User> refQueueObj = new ReferenceQueue<User>(); 
        PhantomReference<User> phantomRef = new PhantomReference<User>(userRefObj.info(),refQueueObj); 
        System.out.println("4 : " + phantomRef);     
       
    } 
}

Выход :

1 :null
Info method invoked from User class
Info method invoked from User class
2 : java.lang.ref.WeakReference@15db9742
Info method invoked from User class
3 : java.lang.ref.SoftReference@6d06d69c
Info method invoked from User class
4 : java.lang.ref.PhantomReference@7852e922

Сомнение: как мы решаем, какой тип ссылки использовать и где именно использовать в реальном сценарии?


person Amit kumar    schedule 07.02.2021    source источник
comment
В 99% случаев вы используете старые добрые нормальные сильные ссылки и не беспокоитесь об остальном. На самом деле они просто используются в некоторых специализированных случаях использования (таких как кэши, чувствительные к памяти, которые также очень трудно сделать правильно). Обычно они спрятаны внутри выделенных библиотек, которые их используют.   -  person Joachim Sauer    schedule 07.02.2021
comment
Да. Я понимаю. Но какой смысл иметь 4 разных ссылочных типа, когда мы в конечном итоге используем сильные ссылки на типы большую часть времени?   -  person Amit kumar    schedule 07.02.2021
comment
Потому что для другого 1% нам нужна другая эталонная семантика.   -  person Turing85    schedule 07.02.2021
comment
Ссылочные джунгли имеют смысл в среде, где ресурсы ограничены. Например, приложения для Android.   -  person Murat Karagöz    schedule 07.02.2021
comment
Это все равно, что спрашивать, почему у поваров есть специальные ножи, ну, нам с вами они не нужны, но они точно нужны. Также обратите внимание, что вы неправильно понимаете их, возможно, вы захотите больше задокументировать себя.   -  person Eugene    schedule 07.02.2021
comment
Спасибо @Eugene. Этот контраст открыл мне глаза. Кроме того, было бы очень полезно, если бы вы могли указать, где я ошибаюсь, пытаясь понять концепцию. Это новое для меня, и я не могу понять.   -  person Amit kumar    schedule 07.02.2021


Ответы (2)


Это сложный ответ, особенно часть реального мира. Эти специальные ссылки являются (очень) острым инструментом для использования, к нему следует прикасаться редко и с очень хорошим пониманием. Ваше первое заблуждение состоит в том, что только Phantom References используют queue (называемый ReferenceQueue). Фактически, они все используют queue. PhantomReference был немного странным среди всех, главным образом потому, что спецификация вокруг него изменилась с java-8 на java-9. Вы можете прочитать этот ответ, чтобы получить некоторые подробности (причины сохранения экземпляра в java-8 на данный момент неизвестны).

Тогда распространенное заблуждение, которое вы получаете, заключается в том, что следующий запуск, для получения более подробной информации, вы можете -cycles-before-it-can/60628663#60628663">посмотрите здесь. Понятие второго или следующего здесь немного сложно; но дело в том, что это недетерминировано.

Приводить примеры из реального мира тоже немного сложно. Это происходит из-за того, что вы редко используете эти ссылки напрямую, они обычно поставляются предварительно упакованными в утилитах. Например, вы можете ">посмотрите, как работает WeakHashMap (который напрямую использует WeakReference и ReferenceQueue под капотом), или событие этот ответ . guava с его CacheBuilder, используемым для предоставления некоторых функций, связанных с SoftReferences (но не больше), кофеин по-прежнему действует.

PhantomReferences используются внутренне для Cleaner API (начиная с java-9). вот пример, показывающий его общее использование. Без PhantomReferences это было бы невозможно (по крайней мере, не так просто).


В этом смысле мы используем WeakHashMap в производстве (мы используем Cleaner API, но гораздо реже). Если вы действительно хотите узнать о них, вам нужно понять, как работает garbage collector (например, действительно работает), затем прочитать их официальную документацию и попробовать (и спросить) несколько вещей.

person Eugene    schedule 08.02.2021
comment
Огромное спасибо Евгений. Это действительно полезно! - person Amit kumar; 08.02.2021

Фактический ответ довольно прост: одних сильных ссылок недостаточно. Вам определенно нужна концепция слабых ссылок в реальном производственном коде.

Тогда можно было бы утверждать, что другие типы просто переработаны. Разработчики языка предполагали, что они будут полезны, но, кроме очень неясных ситуаций, это не так. Но обратите внимание: соответствующая семантика не может быть выполнена с помощью обычного java-кода. Итак, это один из таких случаев, давайте добавим его в язык на случай, если он нам когда-нибудь понадобится.

Но этот 2-й абзац можно легко рассматривать как мнение, а не как факт.

person GhostCat    schedule 07.02.2021