Garbage Collector di JVM

1. Panoramica

In questo breve tutorial, mostreremo le basi delle diverse implementazioni di JVM Garbage Collection (GC) . Inoltre, scopriremo come abilitare un particolare tipo di Garbage Collection nelle nostre applicazioni.

2. Breve introduzione alla raccolta dei rifiuti

Dal nome, sembra che Garbage Collection si occupi di trovare ed eliminare i rifiuti dalla memoria. Tuttavia, in realtà, Garbage Collection tiene traccia di ogni singolo oggetto disponibile nello spazio heap JVM e rimuove quelli inutilizzati.

In parole semplici, GC funziona in due semplici passaggi noti come Mark and Sweep:

  • Mark - è dove il garbage collector identifica quali pezzi di memoria sono in uso e quali no
  • Sweep: questo passaggio rimuove gli oggetti identificati durante la fase di "mark"

Vantaggi:

  • Nessuna gestione manuale dell'allocazione / deallocazione della memoria perché lo spazio di memoria inutilizzato viene gestito automaticamente da GC
  • Nessun overhead di gestione del puntatore penzolante
  • Gestione automatica della perdita di memoria ( GC da solo non può garantire la soluzione completa alla perdita di memoria, tuttavia, si prende cura di una buona parte di essa)

Svantaggi:

  • Poiché JVM deve tenere traccia della creazione / eliminazione dei riferimenti agli oggetti, questa attività richiede più potenza della CPU oltre all'applicazione originale. Può influire sulle prestazioni delle richieste che richiedono una grande memoria
  • I programmatori non hanno alcun controllo sulla pianificazione del tempo della CPU dedicato alla liberazione di oggetti non più necessari
  • L'utilizzo di alcune implementazioni GC potrebbe causare l'arresto imprevedibile dell'applicazione
  • La gestione automatica della memoria non sarà efficiente quanto la corretta allocazione / deallocazione manuale della memoria

3. Implementazioni GC

JVM ha quattro tipi di implementazioni GC :

  • Garbage Collector seriale
  • Garbage Collector parallelo
  • Garbage Collector CMS
  • G1 Garbage Collector

3.1. Garbage Collector seriale

Questa è l'implementazione GC più semplice, poiché funziona fondamentalmente con un singolo thread. Di conseguenza, questa implementazione GC blocca tutti i thread dell'applicazione quando viene eseguita . Quindi, non è una buona idea usarlo in applicazioni multi-thread come ambienti server.

Tuttavia, al QCon 2012 c'è stato un ottimo discorso da parte degli ingegneri di Twitter sulle prestazioni di Serial Garbage Collector , che è un buon modo per capire meglio questo collector.

Serial GC è il garbage collector preferito per la maggior parte delle applicazioni che non richiedono tempi di pausa ridotti e vengono eseguite su macchine in stile client. Per abilitare Serial Garbage Collector , possiamo utilizzare il seguente argomento:

java -XX:+UseSerialGC -jar Application.java

3.2. Garbage Collector parallelo

È il GC predefinito della JVM e talvolta chiamato Throughput Collectors. A differenza di Serial Garbage Collector , utilizza più thread per la gestione dello spazio di heap . Ma blocca anche altri thread dell'applicazione durante l'esecuzione di GC .

Se usiamo questo GC , possiamo specificare il numero massimo di thread di Garbage Collection e il tempo di pausa, la velocità effettiva e il footprint (dimensione dell'heap).

Il numero di thread del Garbage Collector può essere controllato con l'opzione della riga di comando -XX: ParallelGCThreads = .

L'obiettivo massimo del tempo di pausa (intervallo [in millisecondi] tra due GC ) viene specificato con l'opzione della riga di comando -XX: MaxGCPauseMillis = .

L'obiettivo di velocità effettiva massima (misurato in relazione al tempo impiegato per eseguire la raccolta dei rifiuti rispetto al tempo trascorso al di fuori della raccolta dei rifiuti) è specificato dall'opzione della riga di comando -XX: GCTimeRatio =.

Il footprint di heap massimo (la quantità di memoria heap richiesta da un programma durante l'esecuzione) viene specificato utilizzando l'opzione -Xmx.

Per abilitare Parallel Garbage Collector , possiamo utilizzare il seguente argomento:

java -XX:+UseParallelGC -jar Application.java

3.3. Garbage Collector CMS

L' implementazione CMS (Concurrent Mark Sweep) utilizza più thread del Garbage Collector per la Garbage Collection. È progettato per applicazioni che preferiscono pause di Garbage Collection più brevi e che possono permettersi di condividere le risorse del processore con Garbage Collector mentre l'applicazione è in esecuzione.

In poche parole, le applicazioni che utilizzano questo tipo di GC rispondono in media più lentamente ma non smettono di rispondere per eseguire Garbage Collection.

Un punto rapido da notare qui è che poiché questo GC è simultaneo, un'invocazione di una raccolta di dati inutili esplicita come l'utilizzo di System.gc () mentre il processo simultaneo è in funzione, comporterà un errore / interruzione della modalità simultanea .

Se più del 98% del tempo totale viene impiegato nella garbage collection CMS e viene ripristinato meno del 2% dell'heap, il collector CMS genera un'eccezione OutOfMemoryError . Se necessario, questa funzione può essere disabilitata aggiungendo l'opzione -XX: -UseGCOverheadLimit alla riga di comando.

Questo collector ha anche una modalità conosciuta come modalità incrementale che è stata deprecata in Java SE 8 e potrebbe essere rimossa in una futura versione principale.

Per abilitare il Garbage Collector CMS , possiamo utilizzare il seguente flag:

java -XX:+UseParNewGC -jar Application.java

A partire da Java 9, il Garbage Collector CMS è stato deprecato . Pertanto, JVM stampa un messaggio di avviso se proviamo a usarlo:

>> java -XX:+UseConcMarkSweepGC --version Java HotSpot(TM) 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release. java version "9.0.1"

Inoltre, Java 14 ha completamente abbandonato il supporto CMS:

>> java -XX:+UseConcMarkSweepGC --version OpenJDK 64-Bit Server VM warning: Ignoring option UseConcMarkSweepGC; support was removed in 14.0 openjdk 14 2020-03-17

3.4. G1 Garbage Collector

Garbage Collector G1 (Garbage First) è progettato per applicazioni in esecuzione su macchine multiprocessore con ampio spazio di memoria. È disponibile a partire da JDK7 Update 4 e nelle versioni successive.

Il collector G1 sostituirà il collector CMS poiché è più efficiente in termini di prestazioni.

Unlike other collectors, G1 collector partitions the heap into a set of equal-sized heap regions, each a contiguous range of virtual memory. When performing garbage collections, G1 shows a concurrent global marking phase (i.e. phase 1 known as Marking) to determine the liveness of objects throughout the heap.

After the mark phase is completed, G1 knows which regions are mostly empty. It collects in these areas first, which usually yields a significant amount of free space (i.e. phase 2 known as Sweeping). It is why this method of garbage collection is called Garbage-First.

To enable the G1 Garbage Collector, we can use the following argument:

java -XX:+UseG1GC -jar Application.java

3.5. Java 8 Changes

Java 8u20 ha introdotto un ulteriore parametro JVM per ridurre l'uso non necessario della memoria creando troppe istanze della stessa stringa. Ciò ottimizza la memoria dell'heap rimuovendo i valori String duplicati in un singolo array char [] globale .

Questo parametro può essere abilitato aggiungendo -XX: + UseStringDeduplication come parametro JVM .

4. Conclusione

In questo breve tutorial, abbiamo esaminato le diverse implementazioni di JVM Garbage Collection e i loro casi d'uso.

La documentazione più dettagliata può essere trovata qui.