Identification du collecteur de déchets par défaut dans le JDK 8

De nombreux ouvrages de référance sur la machine virtuelle Java (JVM) indiquent que, pour le JDK 8 en mode Server, la combinaison par défaut des collecteurs de déchets (Garbage Collectors) est Parallel Scavenge pour la jeune génération et Serial Old (souvent nommé PS MarkSweep) pour l'ancienne génération. Cet article explore la réalité technique derrière cette affirmation à travers une série d'expérimentations.

1. Analyse des drapeaux de la ligne de commande

La première étape consiste à interroger la JVM sur ses paramètres par défaut à l'aide de la commande suivante :

java -XX:+PrintCommandLineFlags -version

Le résultat typique sur un environnement 64 bits est le suivant :

-XX:InitialHeapSize=268435456 
-XX:MaxHeapSize=4294967296 
-XX:+PrintCommandLineFlags 
-XX:+UseCompressedClassPointers 
-XX:+UseCompressedOops 
-XX:+UseParallelGC 
java version "1.8.0_202"
Java(TM) SE Runtime Environment (build 1.8.0_202-b08)
Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)

On remarque l'activation de l'option -XX:+UseParallelGC. Historiquement, cette option activait Parallel Scavenge + Serial Old. Cependant, nous allons voir que ce comportement a évolué.

2. Exploration via l'API Java Management

Pour identifier les collecteurs réellement instanciés, nous pouvons utiliser les beans de gestion fournis par le JDK. Voici un script simple pour lister les noms des collecteurs actifs :

import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.List;

public class ExplorateurGC {
    public static void main(String[] args) {
        List<GarbageCollectorMXBean> collecteurs = ManagementFactory.getGarbageCollectorMXBeans();
        for (GarbageCollectorMXBean gc : collecteurs) {
            System.out.println("Collecteur détecté : " + gc.getName());
        }
    }
}

L'exécution produit généralement :

Collecteur détecté : PS Scavenge
Collecteur détecté : PS MarkSweep

L'ambiguïté réside dans le nom PS MarkSweep. Est-ce un alias pour Serial Old ou pour Parallel Old ? Même en activant explicitement -XX:+UseParallelOldGC, le nom renvoyé par l'API reste identique, ce qui suggère que PS MarkSweep est un identifiant générique pour l'algorithme de marquage-balayage de l'ancienne génération au sein de la famille "Parallel".

3. Distinction par les journaux détaillés (GC Logs)

Pour lever le doute, l'analyse des statistiques de la mémoire après exécution est nécessaier. L'option -XX:+PrintGCDetails permet de visualiser la structure du tas (heap).

java -XX:+UseParallelGC -XX:+PrintGCDetails ExplorateurGC

Dans la sortie, examinez la section relative à l'ancienne génération :

Heap
 PSYoungGen      total 76288K, used 5243K [...]
  eden space 65536K, 8% used [...]
  from space 10752K, 0% used [...]
  to   space 10752K, 0% used [...]
 ParOldGen       total 175104K, used 0K [...]
  object space 175104K, 0% used [...]
 Metaspace       used 2708K, capacity 4486K, committed 4864K, reserved 1056768K

Le terme ParOldGen confirme l'utilisation de Parallel Old. Si la JVM utilisait Serial Old, nous verrions apparaître PSOldGen.

4. Forcer l'ancien comportement

Si nous désactivons explicitement la compaction parallèle avec -XX:-UseParallelOldGC, le comportement change :

java -XX:+UseParallelGC -XX:-UseParallelOldGC -XX:+PrintGCDetails ExplorateurGC

Résultat dans les logs :

PSOldGen        total 175104K, used 0K [...]

Ici, PSOldGen indique que le collecteur série est utilisé pour la vieille génération. Cela prouve que par défaut (quand seul -XX:+UseParallelGC est présent), le JDK 8 préfère la version parallèle.

5. Origine de la confusion

La documentation officielle du JDK 8 précise que la "compaction parallèle" est activée par défaut dès lors que -XX:+UseParallelGC est utilisé sur une machine de classe serveur. Ce changement a été introduit avec la mise à jour JDK 7u4.

Avant cette version, -XX:+UseParallelGC n'activait effectivement que le collecteur parallèle pour la jeune génération. Mais depuis que Parallel Old a été jugé suffisamment stable et performant, il est devenu le partenaire par défaut de Parallel Scavenge. Les ressources pédagogiques plus anciennes ne reflètent pas toujours cette mise à jour majeure du comportement ergonomique de HotSpot.

Synthèse technique

  • Combinaison par défaut (JDK 8 Server) : Parallel Scavenge + Parallel Old.
  • Drapeau principal : -XX:+UseParallelGC (qui inclut implicitement -XX:+UseParallelOldGC).
  • Identification : Le nom JMX PS MarkSweep est trompeur ; seule la mention ParOldGen dans les logs GC garantit l'utilisation du mode parallèle pour l'ancienne génération.

Étiquettes: JVM garbage-collection java-8 HotSpot performance

Publié le 11 septembre à 18h34