ProgrammazioneSviluppatore Java

Come funziona il meccanismo di gestione automatica della memoria in Java (Garbage Collector)?

Supera i colloqui con l'assistente IA Hintsage

Risposta

In Java la gestione della memoria è effettuata tramite la raccolta automatica dei rifiuti (Garbage Collector, GC). La JVM traccia automaticamente gli oggetti in memoria: se non ci sono più riferimenti a un oggetto, esso diventa inaccessibile e può essere eliminato.

Il GC è composto da diverse fasi, come Mark, Sweep e a volte Compact. Nella fase Mark, gli oggetti raggiungibili dalle radici (GC roots) vengono contrassegnati come vivi. Successivamente, inizia la fase Sweep: gli oggetti non utilizzati vengono eliminati. A volte viene eseguita la fase Compact, ovvero la deframmentazione della memoria.

Ci sono diversi tipi di GC: Serial, Parallel, CMS, G1. È consigliabile scegliere in base al tipo di carico sull'applicazione.

Esempio di codice — situazione di perdita di memoria:
List<byte[]> dataList = new ArrayList<>(); while(true) { dataList.add(new byte[1024*1024]); // Gli oggetti rimangono accessibili }

In questo esempio, gli oggetti non diventeranno mai inaccessibili, il GC non li eliminerà e si verificherà un OutOfMemoryError.

Domanda trabocchetto

Se un oggetto non ha più riferimenti, quando si garantisce la chiamata del suo finalizzatore (finalize())?

Risposta: La chiamata al metodo finalize() non è garantita affatto! Può non essere mai chiamato o essere chiamato con ritardo. Non ci si può fare affidamento su finalize() per liberare risorse.

@Override protected void finalize() throws Throwable { // Potrebbe non essere eseguito! }

Esempi di errori reali a causa della mancanza di conoscenza delle sottigliezze del tema


Storia

In un grande sistema di e-commerce, gli sviluppatori speravano di automatizzare la pulizia dei file temporanei utilizzando il metodo finalize(), ma a causa della rara chiamata di questo metodo, la cache è stata riempita di file temporanei, causando mancanza di spazio su disco e downtime.


Storia

In un'API REST ad alta capacità, è stata accidentalmente mantenuta una cache interna di riferimenti a grandi oggetti, impedendo il rilascio della memoria. Dopo il crash dell'applicazione con OutOfMemoryError, l'analisi ha rivelato un errore nel metodo di caching.


Storia

I finalizzatori sono stati utilizzati per liberare connessioni di rete, considerandoli un "modo affidabile". Questo portava a una situazione in cui le connessioni rimanevano aperte nel sistema per un tempo indefinito, causando blocchi e esaurimento del pool di connessioni.