Rilevare e correggere i memory leak
Individui i pattern comuni dei memory leak, come collezioni statiche, listener e cache, e li corregga.
Rilevare e correggere i memory leak è una lezione Java Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Java Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Java Academy include 4 lezioni in totale.
Che cos'è una perdita di memoria in Java?
Una perdita di memoria in Java si verifica quando gli oggetti non sono più necessari, ma restano fortemente raggiungibili, impedendo al GC di recuperarne la memoria. L'heap cresce finché viene generato un OutOfMemoryError.
Accumulo in una collezione statica
Un campo statico che contiene una collezione in crescita è una causa classica di memory leak. Gli oggetti aggiunti ma mai rimossi restano vivi per tutta la durata dell'applicazione.
public class Cache {
// LEAK: static list grows forever if items are never removed
private static final List<Object> items = new ArrayList<>();
public static void add(Object o) { items.add(o); }
// Fix: add a remove() method or use a bounded cache
}Listener di eventi non rimossi
Registrare un listener senza rimuoverlo mai mantiene vivi sia il listener sia gli oggetti a cui fa riferimento. Rimuova sempre i listener quando non sono più necessari.
// Leak:
sensor.addListener(new DataLogger());
// Fix:
DataLogger logger = new DataLogger();
sensor.addListener(logger);
// ... when done:
sensor.removeListener(logger);Variabili ThreadLocal non ripulite
Nei thread pool, i valori ThreadLocal sopravvivono tra un'attività e l'altra perché i thread vengono riutilizzati. Se non vengono cancellati, i dati di un'attività si propagano alle attività successive eseguite sullo stesso thread.
private static final ThreadLocal<MyContext> CTX = new ThreadLocal<>();
// Always clean up after each task:
try {
CTX.set(new MyContext(requestId));
doWork();
} finally {
CTX.remove(); // prevents leak in pooled threads
}Perdite del classloader nelle applicazioni con hot deploy
Nei servlet container, ogni deployment utilizza un nuovo classloader. Se una classe mantiene un riferimento statico a una classe del classloader precedente, l'intero vecchio classloader, insieme a tutte le sue classi, non può essere raccolto dal GC.
Rilevare le perdite con gli heap dump
Esegua un heap dump con jmap -dump:format=b,file=heap.hprof <pid>, quindi lo apra in Eclipse MAT o VisualVM per trovare gli oggetti trattenuti più grandi e le relative radici GC.
// Take a heap dump:
jmap -dump:live,format=b,file=heap.hprof $(jps | grep MyApp | cut -d" " -f1)
// Or trigger on OOM:
// -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heap.hprofEclipse Memory Analyzer (MAT)
Il report "Leak Suspects" di MAT identifica automaticamente gli oggetti con una grande quantità di memoria heap trattenuta e mostra il percorso dalle radici GC. Inizi dalla vista "Dominator Tree" per trovare i principali responsabili.
Utilizzare WeakReference per evitare le perdite
Avvolga gli oggetti memorizzati nella cache o gli oggetti listener in WeakReference. Il GC può recuperarli quando la memoria scarseggia. Verifichi sempre che il risultato di get() non sia null.
Map<String, WeakReference<Image>> imageCache = new HashMap<>();
imageCache.put("logo", new WeakReference<>(loadImage("logo.png")));
Image logo = imageCache.get("logo") != null ? imageCache.get("logo").get() : null;
if (logo == null) logo = reload("logo.png"); // re-load if GCedCache con dimensione limitata e LinkedHashMap LRU
Esegua l'override di removeEldestEntry in una LinkedHashMap per limitare le dimensioni della cache ed espellere automaticamente la voce meno utilizzata di recente.
Map<String, String> lruCache = new LinkedHashMap<>(16, 0.75f, true) {
protected boolean removeEldestEntry(Map.Entry<String, String> e) {
return size() > 100; // evict when over 100 entries
}
};Profilare le allocazioni con Java Flight Recorder
JFR (Java Flight Recorder) acquisisce i profili delle allocazioni con un overhead minimo. Lo abiliti con -XX:StartFlightRecording e analizzi i dati con JDK Mission Control.
// Start a 60-second JFR recording:
java -XX:StartFlightRecording=duration=60s,filename=rec.jfr MyApp
// Or via jcmd:
jcmd <pid> JFR.start duration=60s filename=rec.jfrCorreggere le perdite: checklist
Verifichi: raccolte statiche, listener non deregistrati, ThreadLocal nei pool, perdite di connessioni o stream (utilizzi try-with-resources), riferimenti da classi interne agli oggetti esterni e cache senza espulsione.
Verifica rapida
Quale flag della JVM esegue automaticamente un dump dell'heap quando viene generato un OutOfMemoryError?
Riepilogo
Fonti comuni di perdite in Java: raccolte statiche, listener non deregistrati, ThreadLocal nei pool e cache senza limiti. Le rilevi con gli heap dump e MAT. Le corregga utilizzando WeakReference, strutture con dimensione limitata e rimuovendo sempre i riferimenti quando non servono più.
Domande Frequenti
La lezione «Rilevare e correggere i memory leak» è gratuita?
Sì — il testo completo di «Rilevare e correggere i memory leak» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Java Academy, passa a CoddyKit PRO. Il corso Java Academy include 4 lezioni in totale.
Cosa imparerò in «Rilevare e correggere i memory leak»?
Individui i pattern comuni dei memory leak, come collezioni statiche, listener e cache, e li corregga. Eserciti Java Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Java Academy?
Non è richiesta alcuna esperienza precedente. Java Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Rilevare e correggere i memory leak»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Java Academy?
Sì. Ogni lezione Java Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Regioni dell'heap della JVM e ciclo di vita degli oggetti
- Algoritmi GC: Serial, G1, ZGC, Shenandoah
- Rilevare e correggere i memory leak
- Flag per il tuning del GC e profiling con JVisualVM