8.1 Riferimenti deboli in Java

Esistono diversi tipi di riferimenti in Java.

C'è StrongReference : questi sono i collegamenti più comuni che creiamo ogni giorno.

Object object = new Object();//created an object
object = null;//can now be garbage collected

E ci sono tre tipi di collegamenti "speciali": SoftReference, WeakReference, PhantomReference. In effetti, c'è solo una differenza tra tutti i tipi di collegamenti: il comportamento del GC con gli oggetti a cui si riferiscono. Discuteremo le specifiche di ciascun tipo di collegamento in modo più dettagliato in seguito, ma per ora sarà sufficiente la seguente conoscenza:

  • SoftReference è un riferimento soft, se il GC vede che un oggetto è accessibile solo attraverso una catena di riferimenti soft, lo rimuoverà dalla memoria. Forse.
  • WeakReference - un riferimento debole, se il GC vede che un oggetto è accessibile solo attraverso una catena di riferimenti deboli, lo rimuoverà dalla memoria.
  • PhantomReference è un riferimento fantasma, se il GC vede che un oggetto è disponibile solo attraverso una catena di riferimenti fantasma, lo rimuoverà dalla memoria. Dopo diverse corse di GC.

Puoi anche dire che i tipi di collegamento hanno un certo grado di morbidezza:

  • Un hard link regolare è qualsiasi variabile di un tipo di riferimento. Non ripulito dal Garbage Collector prima che diventi inutilizzato.
  • SoftReference . L'oggetto non causerà l'esaurimento di tutta la memoria: è garantito che venga eliminato prima che si verifichi un OutOfMemoryError. Forse prima, a seconda dell'implementazione del Garbage Collector.
  • Riferimento debole . Più debole morbido. Non impedisce l'eliminazione dell'oggetto; il Garbage Collector ignora tali riferimenti.
  • Riferimento fantasma . Utilizzato per l'elaborazione "morte" di un oggetto: l'oggetto è disponibile dopo la finalizzazione fino a quando non viene sottoposto a Garbage Collection.

Se non è ancora chiaro quale sia la differenza, non preoccuparti, presto tutto andrà a posto. I dettagli sono nei dettagli e i dettagli seguiranno.

8.2 WeakReference e SoftReference in Java

Innanzitutto, diamo un'occhiata alla differenza tra WeakReference e SoftReference in Java.

In breve, il Garbage Collector libererà la memoria di un oggetto se solo riferimenti deboli lo puntano. Se l'oggetto è puntato da SoftReferences, la memoria viene deallocata quando la JVM ha un disperato bisogno di memoria.

Ciò offre un netto vantaggio a SoftReference rispetto a Strong reference in alcuni casi. Ad esempio, SoftReference viene utilizzato per implementare una cache dell'applicazione, quindi la prima cosa che farà JVM è eliminare gli oggetti a cui puntano solo SoftReferences.

WeakReference è ottimo per l'archiviazione di metadati, come l'archiviazione di un riferimento a un ClassLoader. Se non viene caricata alcuna classe, non dovresti fare riferimento a ClassLoader. Questo è il motivo per cui WeakReference consente al Garbage Collector di svolgere il proprio lavoro sul ClassLoader non appena viene rimosso l'ultimo riferimento forte ad esso.

Esempio di WeakReference in Java:

// some object
Student student = new Student();

// weak reference to it
WeakReference weakStudent = new WeakReference(student);

// now the Student object can be garbage collected
student = null;

Esempio di SoftReference in Java:

// some object
Student student = new Student();

// weak reference to it
SoftReference softStudent = new SoftReference(student)

// now the Student object can be garbage collected
// but this will only happen if the JVM has a strong need for memory
student = null;

8.3 Riferimento fantasma in Java

L'istanza PhantomReference viene creata nello stesso modo degli esempi WeakReference e SoftReference, ma viene utilizzata raramente.

Un PhantomReference può essere sottoposto a Garbage Collection se l'oggetto non dispone di riferimenti forti (Strong), deboli (WeakReference) o soft (SoftReference).

Puoi creare un oggetto di riferimento fantasma come questo:

PhantomReference myObjectRef = new PhantomReference(MyObject);

PhantomReference può essere utilizzato in situazioni in cui finalize() non ha senso. Questo tipo di riferimento è diverso dagli altri tipi perché non è progettato per accedere a un oggetto. È un segnale che l'oggetto è già stato finalizzato e il Garbage Collector è pronto a recuperare la sua memoria.

Per fare ciò, il Garbage Collector lo inserisce in una speciale ReferenceQueue per un'ulteriore elaborazione. ReferenceQueue è il punto in cui vengono posizionati i riferimenti agli oggetti per liberare memoria.

I riferimenti fantasma sono un modo sicuro per sapere che un oggetto è stato rimosso dalla memoria. Ad esempio, considera un'applicazione che si occupa di immagini di grandi dimensioni. Supponiamo di voler caricare un'immagine in memoria quando è già in memoria, che è pronta per la raccolta dei rifiuti. In questo caso, vogliamo aspettare che il Garbage Collector elimini la vecchia immagine prima di caricare la nuova immagine in memoria.

Qui PhantomReference è una scelta flessibile e sicura. Il riferimento alla vecchia immagine verrà passato a ReferenceQueue dopo che il vecchio oggetto immagine è stato distrutto. Una volta che abbiamo questo collegamento, possiamo caricare la nuova immagine in memoria.