2012-02-06 12 views
7

Javadocs dice "Quando una chiave è stata scartata, la sua entrata è effettivamente rimossa dalla mappa" ".WeakHashMap e valore fortemente referenziato

Ma a meno che non vi sia un altro thread che occasionalmente rimuove tali voci Map.Entry, gli oggetti valore non saranno fortemente referenziati dalla mappa? Ma poiché non esiste un thread in esecuzione, solo le chiamate del metodo get possono rimuovere tali voci, una alla volta.

Quasi sempre utilizzo WeakHashMap<K, WeakReference<V>> per questo motivo. Perché non avrebbero dovuto farlo come comportamento predefinito? Valgono anche i riferimenti deboli?

+0

http://stackoverflow.com/questions/2473410/question-about-weakhashmap è quasi una domanda identica. Ma volevo sapere se la mia asserzione è corretta: una voce verrà rimossa solo quando get() scopre che la chiave è stata gc, e che francamente non sembra avere un grande valore se non utilizzo WeakReferences come valori. –

+0

Sì, è solo un sondaggio. Se vuoi qualcosa di diverso, scrivi la tua versione. –

+2

Se hai bisogno di qualcosa di diverso, usa una biblioteca: scrivere la tua è super difficile. Guava ha 'MapMaker', che ti permette di configurare la forza dei riferimenti chiave e valore: http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/MapMaker. html –

risposta

8

Le code di riferimento vengono utilizzate per rimuovere automaticamente le voci.

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

code di riferimento, a cui registrata oggetti di riferimento vengono aggiunti dal garbage collector dopo vengono rilevate le modifiche appropriate raggiungibilità.

Fondamentalmente, riferimenti deboli sono una parte fondamentale del garbage collector, quindi quando una spazzata GC accade, riferimenti inutilizzati sono trovati e messi nelle code e quindi si può intervenire in base al contenuto di tali code.

Un thread può sedersi sul metodo remove della coda per essere avvisati quando è necessario eseguire la pulizia o poll la coda.

"Java theory and practice: Plugging memory leaks with weak references" spiega:

L'attuazione di WeakHashMap illustra un linguaggio comune con riferimenti deboli - che qualche oggetto interno si estende WeakReference.

...

WeakHashMap utilizza riferimenti deboli per tenere le chiavi della mappa, che consente gli oggetti chiave da spazzatura raccolti quando non sono più utilizzati dall'applicazione, e l'implementazione get() può dire una mappatura in diretta da una uno morto se WeakReference.get() restituisce null. Ma questa è solo la metà di ciò che è necessario per mantenere il consumo di memoria di una mappa da aumentare per tutta la durata dell'applicazione; qualcosa deve essere fatto anche per potare le voci morte dalla mappa dopo che l'oggetto chiave è stato raccolto. Altrimenti, la Mappa si riempirebbe semplicemente di voci corrispondenti a chiavi morte. E anche se questo sarebbe invisibile all'applicazione, potrebbe comunque causare l'esaurimento della memoria dell'applicazione perché gli oggetti Map.Entry e value non verrebbero raccolti, anche se la chiave è.

...

code Riferimento sono mezzi primari i rifiuti da collezione di retroazione informazioni all'applicazione su oggetto ciclo di vita. I riferimenti deboli hanno due costruttori: uno prende solo il referente come argomento e l'altro prende anche una coda di riferimento. Quando un riferimento debole è stato creato con una coda di riferimento associata e il referente diventa candidato per GC, l'oggetto di riferimento (non il referente) viene accodato alla coda di riferimento dopo che il riferimento è stato cancellato.L'applicazione può quindi recuperare il riferimento dalla coda di riferimento e apprendere che il referente è stato raccolto in modo che possa eseguire attività di pulizia associate, come l'eliminazione delle voci per oggetti che sono caduti da una collezione debole. (Code di riferimento offrono le stesse modalità di annullamento dell'accodamento come BlockingQueue - intervistati, il blocco a tempo, e il blocco senza orario.)

EDIT:

Anche con le code, le mappe debole può ancora perdere. Ephemerons sono un tentativo di risolvere il caso in cui una chiave debole fa riferimento a un valore fortemente considerato che fa riferimento alla chiave. Non sono implementabili in java.

Gli effemeroni risolvono un problema che si riscontra comunemente quando si tenta di "collegare" proprietà agli oggetti utilizzando un registro. Quando alcune proprietà devono essere associate a un oggetto, la proprietà dovrebbe (in termini di comportamento GC) avere in genere la durata di vita di una variabile di istanza di questo oggetto. Tuttavia, questo è complicato da avere un'associazione esterna tra l'oggetto e la proprietà quali:

property --------- registry --------- association --------- object 

Qui, nel registro (terzi) sarà trattenere l'associazione stessa che richiederebbe la rimozione manuale dal registro (invece della raccolta automatica dei rifiuti). Sebbene questo problema possa sempre essere risolto in una data situazione concreta usando uno dei vari tipi di associazione deboli, la scelta del tipo "giusto" di associazione dipende da una varietà di fattori, alcuni dei quali possono cambiare dinamicamente.

Gli effemeroni risolvono questo problema definendo che i "contenuti" (valore) di un effemerone verranno mantenuti con fermezza fino a quando la chiave non sarà raccolta. Da quel momento in poi, il contenuto dell'effimero si terrà debolmente. Pertanto, il contenuto di un effemerone può diventare idoneo per la garbage collection se e solo se la chiave è garbage collectable che è il comportamento esatto che osserveremmo per una variabile di istanza dell'oggetto.

+0

Hai dimenticato la capacità della coda di riferimento di chiamare il nostro hook. –

+0

Ho trovato dal tuo link "WeakHashMap ha un metodo privato chiamato expungeStaleEntries() che viene chiamato durante la maggior parte delle operazioni della mappa." per essere utile. E mi chiedo se la generazione di una discussione che effettivamente farebbe letture di blocco sulla coda di riferimento potrebbe essere un'idea migliore. Forse è quello che fa MapMaker di Guava. –

+1

@UstamanSangat, non so cosa faccia MapMaker, ma forse expungeStaleEntries() esegue il polling della coda di riferimento per ammortizzare la pulizia con l'uso della mappa. Vorrei provare a utilizzare qualcosa come MapMaker prima di passare all'applicazione della mia pulizia delle chiavi.A proposito, ho aggiunto una modifica che indica i modi in cui è possibile perdere memoria anche utilizzando mappe chiave deboli. –

Problemi correlati