"Ciao! Ho deciso di darti un'altra piccola lezione sulla raccolta dei rifiuti."

Come già sai, la macchina Java stessa monitora quando un oggetto diventa non necessario e lo elimina.

"Sì. Tu e Rishi me ne avete parlato prima. Non ricordo i dettagli."

"OK. Allora ripassiamolo di nuovo."

Raccolta dei rifiuti - 1

"Non appena viene creato un oggetto, la JVM alloca memoria per esso. L'interesse per l'oggetto viene monitorato utilizzando variabili di riferimento.  Un oggetto può essere cancellato durante la garbage collection, ovvero la procedura con cui viene rilasciata memoria se non ci sono variabili che fanno riferimento all'oggetto oggetto. "

"Parlami un po' del netturbino: cos'è e come funziona."

"OK. La raccolta dei dati inutili avveniva sul thread principale. Ogni 5 minuti, o più spesso. Se non c'era memoria libera sufficiente, la macchina Java sospendeva tutti i thread ed eliminava gli oggetti inutilizzati."

"Ma questo approccio è stato abbandonato ora. Il Garbage Collector di nuova generazione lavora dietro le quinte e su un thread separato. Questo si chiama Garbage Collection concorrente".

"Capisco. Com'è esattamente la decisione di eliminare o meno un oggetto?"

"Il solo conteggio del numero di riferimenti a un oggetto non è molto efficace: potrebbero esserci oggetti che fanno riferimento l'uno all'altro, ma non sono referenziati da altri oggetti."

"Quindi Java adotta un approccio diverso.  Java divide gli oggetti in raggiungibili e irraggiungibili.  Un oggetto è raggiungibile (vivo) se viene referenziato da un altro oggetto raggiungibile (vivo). La raggiungibilità è determinata dai thread. I thread in esecuzione sono sempre considerati raggiungibili (vivi) , anche se nessuno li fa riferimento."

"OK. Penso di aver capito."

"Come avviene l'effettiva raccolta dei rifiuti: l'eliminazione di oggetti non necessari?"

"È semplice. In Java, la memoria è divisa in due parti per convenzione, e quando è il momento della raccolta dei rifiuti, tutti gli oggetti viventi (raggiungibili) vengono copiati in un'altra parte della memoria, e la vecchia memoria viene tutta rilasciata."

"Questo è un approccio interessante. Non c'è bisogno di contare i riferimenti: copia tutti gli oggetti raggiungibili e tutto il resto è spazzatura."

"È un po' più complicato di così. I programmatori Java hanno scoperto che gli oggetti sono generalmente divisi in due categorie: di lunga durata (che esistono per tutto il tempo in cui il programma è in esecuzione) e di breve durata (che sono necessari nei metodi e per eseguire «local » operazioni)."

"È molto più efficiente tenere separati gli oggetti di lunga durata da quelli di breve durata. Per fare ciò, era necessario trovare un modo per determinare la longevità dell'oggetto".

"Quindi, hanno diviso tutta la memoria in «generazioni». Ci sono oggetti di prima generazione, oggetti di seconda generazione, ecc. Ogni volta che la memoria viene cancellata, il contatore di generazione viene incrementato di 1. Se certi oggetti esistono in più generazioni, allora sono registrati come longevi."

"Oggi, il Garbage Collector è una parte molto complessa ed efficiente di Java. Molte delle sue parti funzionano in modo euristico, sulla base di algoritmi che fanno supposizioni. Di conseguenza, spesso "non ascolta" l'utente."

"Senso?"

"Java ha un oggetto Garbage Collector ( GC ) che può essere chiamato utilizzando il metodo System.gc ()."

"Puoi anche usare System.runFinalization() per forzare le chiamate ai metodi finalize degli oggetti da eliminare. Ma il fatto è che, secondo la documentazione Java, questo non garantisce né l'avvio della garbage collection, né che il finalize( ) verrà chiamato.  Il Garbage Collector decide quando chiamarlo e su cosa. "

"Ehi! Buono a sapersi."

"Ma c'è di più. Come sai, in Java, alcuni oggetti fanno riferimento ad altri. Questa rete di riferimenti viene utilizzata per determinare se un oggetto debba essere cancellato."

"E, guarda. Java ha riferimenti speciali che ti consentono di influenzare questo processo. Ci sono classi wrapper speciali per loro. Eccoli:"

" SoftReference  è un riferimento soft."

" WeakReference  è un riferimento debole."

" PhantomReference è un riferimento fantasma."

"Uh... Questo mi ricorda le classi interne, le classi annidate, le classi anonime annidate e le classi locali. I nomi sono diversi, ma non è affatto chiaro a cosa servano."

"Dì, Amigo, sei diventato un programmatore. Ora sei arrabbiato a causa dei nomi delle classi, dicendo «non sono abbastanza informativi, ed è impossibile con un nome (!) determinare cosa fa questa classe, come, e perché"."

"Wow. Non me ne sono nemmeno accorto. Ma è così ovvio."

"OK. Abbastanza parole. Lascia che ti parli di SoftReferences."

"Questi riferimenti sono stati specificamente progettati per la memorizzazione nella cache, sebbene possano essere utilizzati per altri scopi, tutto a discrezione del programmatore."

"Ecco un esempio di tale riferimento:"

Esempio
// Create a Cat object
Cat cat = new Cat();

// Create a soft reference to a Cat object
SoftReference<Cat> catRef = new SoftReference<Cat>(cat);

// Now only the catRef soft reference points at the object
cat = null;

// Now the ordinary cat variable also references the object
cat = catRef.get();

// Clear the soft reference
catRef.clear();

"Se gli unici riferimenti a un oggetto sono morbidi, allora continua a vivere e si chiama 'dolcemente raggiungibile'."

"Ma!  Un oggetto referenziato solo da riferimenti software può essere eliminato dal Garbage Collector se il programma non ha memoria sufficiente.  Se improvvisamente il programma non ha memoria sufficiente, prima di lanciare un OutOfMemoryException , il Garbage Collector eliminerà tutti gli oggetti referenziato da riferimenti soft e riproverà ad allocare memoria al programma."

"Supponiamo che un programma client richieda frequentemente vari dati da un programma server. Il programma server può utilizzare un SoftReference per memorizzarne alcuni nella cache. Se gli oggetti preservati dalla morte dai riferimenti software occupano gran parte della memoria, il Garbage Collector li elimina semplicemente tutto. È bellissimo!"

"Sì. Mi è piaciuto anch'io."

"Bene, una piccola aggiunta: la classe SoftReference ha due metodi. Il metodo get() restituisce l'oggetto a cui fa riferimento SoftReference . Se l'oggetto è stato eliminato dal Garbage Collector, il metodo get () inizierà improvvisamente a restituire null."

"L'utente può anche cancellare esplicitamente SoftReference chiamando il metodo clear(). In questo caso, l'anello debole all'interno dell'oggetto SoftReference verrà distrutto."

"È tutto per ora."

"Grazie per l'interessante storia, Ellie. È stata davvero molto interessante."