Riferimenti deboli in Java

1. Panoramica

In questo articolo, daremo uno sguardo al concetto di riferimento debole - nel linguaggio Java.

Spiegheremo cosa sono, a cosa servono e come lavorarci correttamente.

2. Riferimenti deboli

Un oggetto debolmente referenziato viene cancellato dal Garbage Collector quando è debolmente raggiungibile.

Raggiungibilità debole significa che un oggetto non ha riferimenti né forti né morbidi che lo puntino . L'oggetto può essere raggiunto solo attraversando un riferimento debole.

Prima di tutto, il Garbage Collector cancella un riferimento debole, quindi il referente non è più accessibile. Quindi il riferimento viene inserito in una coda di riferimento (se esiste uno associato) da cui è possibile ottenerlo.

Allo stesso tempo, verranno finalizzati oggetti precedentemente debolmente raggiungibili.

2.1. Riferimenti deboli e morbidi

A volte la differenza tra riferimenti deboli e morbidi non è chiara. I riferimenti morbidi sono fondamentalmente una grande cache LRU. Cioè, usiamo riferimenti morbidi quando il referente ha buone possibilità di essere riutilizzato nel prossimo futuro .

Poiché un riferimento software funge da cache, può continuare a essere raggiungibile anche se il referente stesso non lo è. È un dato di fatto, un riferimento morbido è idoneo per la raccolta se e solo se:

  • Il referente non è fortemente raggiungibile
  • Il riferimento software non è stato eseguito di recente

Quindi un riferimento morbido può essere disponibile per minuti o anche ore dopo che il referente diventa irraggiungibile. D'altra parte, un riferimento debole sarà disponibile solo fino a quando il suo referente sarà ancora in giro.

3. Casi d'uso

Come affermato dalla documentazione Java, i riferimenti deboli vengono spesso utilizzati per implementare i mapping canonicalizzanti . Una mappatura viene chiamata canonicalizzata se contiene solo un'istanza di un particolare valore. Piuttosto che creare un nuovo oggetto, cerca quello esistente nella mappatura e lo utilizza.

Ovviamente, l' uso più noto di questi riferimenti è la classe WeakHashMap . È l'implementazione dell'interfaccia Map in cui ogni chiave viene memorizzata come riferimento debole alla chiave data. Quando il Garbage Collector rimuove una chiave, viene eliminata anche l'entità associata a questa chiave.

Per ulteriori informazioni, consulta la nostra guida a WeakHashMap.

Un'altra area in cui possono essere utilizzati è il problema dell'ascoltatore scaduto .

Un editore (o un soggetto) mantiene forti riferimenti a tutti gli abbonati (o ascoltatori) per informarli sugli eventi accaduti. Il problema sorge quando un ascoltatore non può annullare correttamente l'iscrizione a un editore.

Pertanto, un listener non può essere sottoposto a Garbage Collection poiché un forte riferimento a è ancora disponibile per un editore. Di conseguenza, possono verificarsi perdite di memoria.

La soluzione al problema può essere un soggetto con un debole riferimento a un osservatore che consenta di raccogliere il primo senza la necessità di essere cancellato (si noti che questa non è una soluzione completa e introduce alcuni altri problemi che non lo sono coperto qui).

4. Lavorare con riferimenti deboli

I riferimenti deboli sono rappresentati dalla classe java.lang.ref.WeakReference . Possiamo inizializzarlo passando un referente come parametro. Facoltativamente, possiamo fornire un java.lang.ref.ReferenceQueue :

Object referent = new Object(); ReferenceQueue referenceQueue = new ReferenceQueue(); WeakReference weakReference1 = new WeakReference(referent); WeakReference weakReference2 = new WeakReference(referent, referenceQueue); 

Il referente di un riferimento può essere recuperato con il metodo get e rimosso manualmente utilizzando il metodo clear :

Object referent2 = weakReference1.get(); weakReference1.clear(); 

Lo schema per lavorare in sicurezza con questo tipo di riferimenti è lo stesso dei riferimenti morbidi:

Object referent3 = weakReference2.get(); if (referent3 != null) { // GC hasn't removed the instance yet } else { // GC has cleared the instance }

5. conclusione

In questo breve tutorial, abbiamo esaminato il concetto di basso livello di un riferimento debole in Java e ci siamo concentrati sugli scenari più comuni per utilizzarli.