Haladó Olvasási idő: ~16 perc

Garbage Collection

GC típusok, G1, ZGC, memóriaszivárgások és hangolás

Garbage Collection

A Garbage Collection (GC) a JVM automatikus memóriakezelési mechanizmusa, amely azonosítja és visszaigényli azoknak az objektumoknak a heap memóriáját, amelyek már nem érhetők el egyetlen élő thread-ből vagy GC gyökérből sem.

1. Definíció

Mi ez?

A Garbage Collection az a folyamat, amelynek során a JVM automatikusan felszabadítja a heap memóriát. A GC periodikusan bejárja az objektumgráfot a GC gyökerektől (élő thread stack-ek, statikus mezők, JNI referenciák) kiindulva, megjelöli az összes elérhető objektumot élőként, és visszaigényli a többit. A programozónak nem kell free()-t hívnia — a JVM kezeli a felszabadítást automatikusan.

Miért létezik?

A manuális memóriakezelés (C/C++) hibára hajlamos: dangling pointer-ek, double-free-k és buffer overrun-ok mind jellemző hibák. A Java GC-je megszünteti ezeket a hibacsoportokat, ugyanakkor pause time-okat (Stop-the-World eseményeket) és némi futásidejű overheadet vezet be. Az egyensúly: helyesség és fejlesztői produktivitás vs. nyers kontroll.

Hova illeszkedik?

A GC teljes egészében a JVM-en belül működik a heap-en. A stack (lokális változók, metódus frame-ek) automatikusan kezelt LIFO push/pop segítségével, GC részvétele nélkül. A heap-en élnek a new-val létrehozott objektumok, és a GC feladata ennek a memóriaterületnek a kezelése.

Fontos JVM memóriaterületek:

  • Stack — threadenként tárolja a metódus frame-eket és lokális változókat; a GC nem ezt kezeli.
  • Heap — a new-val létrehozott objektumok és tömbök helye; ezt kezeli a GC.
  • Metaspace — osztálymetaadatokat és runtime típusinformációt tárol.
  • Code Cache — a JIT által fordított natív kód helye.

2. Alapfogalmak

2.1 GC algoritmusok

Algoritmus Működés Jellemző
Mark-and-Sweep Megjelöli az élő objektumokat, söpri a holtakat Töredezettséget okozhat
Copying Az élő objektumokat új területre másolja, a régit elveti Nincs töredezettség, de a tér felét pazarolja
Mark-Compact Megjelöli az élőket, majd az egyik végre tömöríti őket Nincs pazarlás, de lassabb a tömörítés miatt

A modern GC-k kombinálják ezeket: a Young Gen Copying-ot használ (gyors, az objektumok fiatalon halnak), az Old Gen Mark-Compact-ot vagy concurrent marking-et.


2.2 Generációs hipotézis

„A legtöbb objektum fiatalon hal meg."

Ezen az empirikus megfigyelésen alapulva a heap generációkra van osztva:

A hagyományos heap felosztása röviden:

  • Eden — itt indulnak az újonnan allokált objektumok.

  • Survivor S0/S1 — a Minor GC-t túlélő objektumok ide-oda mozognak és öregszenek.

  • Old Gen — ide kerülnek a hosszú életű objektumok; ritkábban, de drágábban gyűjthető.

  • A Minor GC főleg a fiatal generációt érinti, a Major / Full GC az idősebb adatokat célozza.

  • Eden: Az új objektumok itt foglalnak helyet (TLAB-ok segítségével, thread-helyi gyors allokáció).

  • Survivor S0/S1: A Minor GC-t túlélő objektumok S0 és S1 között másolódnak, minden ciklusban öregedve.

  • Old Gen (Tenured): Az elegendő Minor GC-t túlélő objektumokat (alapértelmezett tenuring küszöb: 15) ide promótálják.


2.3 GC típusok

Serial GC (`-XX:+UseSerialGC`)

  • Egyszálú collector a Young és Old Gen-hez egyaránt.
  • Minden application thread-et megállít (Stop-the-World) a gyűjtés alatt.
  • Mikor érdemes: kis heap-ek (<100 MB), beágyazott/egyszálú környezetek, batch feladatok, ahol a pause elfogadható.

Parallel GC / Throughput GC (`-XX:+UseParallelGC`)

  • Többszálú Minor és Major GC.
  • Még mindig Stop-the-World, de N thread-del gyorsabban végez.
  • Java 9 előtt volt az alapértelmezett. Mikor érdemes: batch feldolgozás, throughput-orientált alkalmazások.

CMS – Concurrent Mark-Sweep (`-XX:+UseConcMarkSweepGC`) ⚠️ Elavult

  • Az Old Gen megjelölésének nagy részét párhuzamosan végzi az alkalmazással, csökkentve a pause time-ot.
  • Fragmentációtól szenved (nincs compaction), concurrent mode failure léphet fel nagy allokáció nyomás esetén.
  • Java 14-ben eltávolítva.

G1 GC – Garbage First (`-XX:+UseG1GC`)

  • Java 9 óta alapértelmezett.
  • Régió-alapú: a heap egyenlő méretű régiókra (~1–32 MB) van osztva, amelyek dinamikusan Eden, Survivor, Old vagy Humongous típust kapnak.
  • Előre jelezhető pause célok a -XX:MaxGCPauseMillis segítségével (alapértelmezett: 200ms).
  • Concurrent marking-et végez; az evakuáció (élő objektumok másolása) STW, de korlátozott.
  • Mikor érdemes: általános célú szerver alkalmazások, 4 GB – 32 GB heap.

A G1-ben a heap sok azonos méretű régióra van bontva, és ezek szerepe dinamikusan változik:

  • E (Eden) — új allokációk régiói.
  • S (Survivor) — a frissen túlélő objektumok régiói.
  • O (Old) — a hosszú életű objektumok régiói.
  • H (Humongous) — a nagyon nagy objektumoknak fenntartott régiók.

ZGC (`-XX:+UseZGC`)

  • Ultra-alacsony latenciájú GC: a pause time < 10 ms, a heap méretétől függetlenül (tesztelve terabájtos heap-en is).
  • A pause-ok nem skálázódnak a heap méretével — csak a gyökérkészlet méretével.
  • Load barrier-eket és colored pointer-eket használ (64 biten) a relokáció párhuzamos elvégzéséhez.
  • Java 11 óta érhető el (kísérleti), Java 15 óta production-kész, Java 21-ben tovább fejlesztve.
  • Mikor érdemes: latencia-érzékeny alkalmazások (kereskedés, játék, real-time rendszerek), nagyon nagy heap-ek.

Shenandoah GC (`-XX:+UseShenandoahGC`)

  • Concurrent compaction GC, a Red Hat fejlesztette, OpenJDK-ban elérhető.
  • Hasonló célok, mint a ZGC: sub-10ms pause-ok concurrent evakuációval.
  • Brooks forwarding pointer-eket használ a concurrent relokációhoz.
  • Mikor érdemes: ugyanazok az esetek, mint ZGC; egyes disztribúciókon érhető el, ahol a ZGC nem.

Epsilon GC (`-XX:+UseEpsilonGC`) 🧪

  • No-op GC: allokál, de soha nem gyűjt. A JVM OOM-mal összeomlik, amikor a heap kimerül.
  • Mikor érdemes: teljesítmény benchmarking (eliminálja a GC zajt), nagyon rövid életű folyamatok.

2.4 GC fázisok

Fázis Kiváltó ok Thread-ek megállnak?
Minor GC Eden megtelik Igen (röviden)
Major GC Old Gen gyűjtést igényel Igen (hosszabban)
Full GC OOM kockázat, explicit System.gc(), CMS failure Igen (leghosszabban)
Concurrent Marking G1/ZGC háttérfázis Nem
Evacuation/Relocation G1 mixed collection, ZGC Részben vagy nem

2.5 GC gyökerek

A GC a GC gyökerektől — garantáltan élő referenciáktól — indítja a bejárást:

  • Lokális változók az aktív thread stack-eken
  • Statikus mezők a betöltött osztályokban
  • JNI referenciák (natív kód Java objektumokat tart)
  • Szinkronizációs monitorok (synchronized-ban használt objektumok)
  • Class loader referenciák

Ami nem érhető el GC gyökérből, az gyűjtésre jogosult.


2.6 Referencia típusok

A Java négy referencia-erősséget kínál, amelyekkel a fejlesztő befolyásolhatja a GC viselkedését:

Típus Osztály GC viselkedés
Strong (alapértelmezett new) Soha nem gyűjtik, amíg elérhető
Soft SoftReference<T> Gyűjtik, ha a JVM memóriára szorul (OOM előtt)
Weak WeakReference<T> A következő GC ciklusban gyűjtik, ha nincs strong ref
Phantom PhantomReference<T> Finalizálás után sorba kerül; cleanup hook-okhoz használatos

3. Gyakorlati használat

A megfelelő GC kiválasztása

Helyzet Ajánlott GC
Batch feldolgozás / max throughput Parallel GC
Általános szerver alkalmazás (Java 9+) G1 GC (alapértelmezett)
Alacsony latencia (<200ms pause, 4–32 GB heap) G1 GC hangolással
Ultra-alacsony latencia (<10ms) vagy nagyon nagy heap ZGC
Benchmarking / GC nélküli rövid folyamat Epsilon GC

Kulcs JVM flag-ek

# Heap méretezés (production-ban MINDIG egyenlőre állítani)
-Xms4g -Xmx4g

# GC kiválasztása
-XX:+UseG1GC          # G1 (alapértelmezett Java 9+)
-XX:+UseZGC           # ZGC
-XX:+UseParallelGC    # Throughput GC
-XX:+UseShenandoahGC  # Shenandoah

# G1 hangolás
-XX:MaxGCPauseMillis=200       # Pause cél (soft target)
-XX:G1HeapRegionSize=16m       # Régió méret (1–32 MB, kettő hatványa)
-XX:InitiatingHeapOccupancyPercent=45  # Concurrent marking indítási küszöb

# ZGC hangolás
-XX:SoftMaxHeapSize=28g        # Soft heap limit

# GC naplózás (Java 9+ unified logging)
-Xlog:gc*:file=gc.log:time,uptime,level,tags:filecount=5,filesize=20m

# Diagnosztika
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/dumps/heap.hprof

Mikor érdemes hangolni

  • Ha a GC pause idők meghaladják az alkalmazás SLA-ját (GC log-ból ellenőrizhető).
  • Ha a GC overhead meghaladja a teljes CPU idő ~5%-át.
  • Amikor gyakori Full GC eseményeket tapasztalunk.
  • Soha ne hangolj vakon — mindig először mérd meg GC logokkal és profilozó eszközökkel (JFR, VisualVM, GCViewer).

Mikor NEM érdemes hangolni

  • Mérés előtt — a korai GC hangolás elvesztegetett erőfeszítés.
  • A heap korlátlan növelésével — a nagyobb heap néhány collector-nál hosszabb GC pause-okat jelent.
  • System.gc() hívásával — a JVM figyelmen kívül hagyhatja, és általában kárt okoz.

4. Kód példák

1. példa: WeakReference memória-érzékeny cache-hez

import java.lang.ref.WeakReference;
import java.util.WeakHashMap;

// WeakHashMap: a kulcsok gyengén referáltak — a bejegyzések automatikusan eltűnnek, ha a kulcs GC-zve lett
public class ImageCache {
    private final WeakHashMap<String, byte[]> cache = new WeakHashMap<>();

    public void put(String key, byte[] data) {
        cache.put(key, data);
    }

    public byte[] get(String key) {
        return cache.get(key); // null lehet, ha a GC visszaigényelte
    }
}

// Explicit WeakReference használat
WeakReference<ExpensiveObject> weakRef = new WeakReference<>(new ExpensiveObject());
ExpensiveObject obj = weakRef.get(); // null, ha a GC futott
if (obj != null) {
    obj.doWork();
}

// SoftReference cache-ekhez, amelyek lehetőleg maradjanak meg
import java.lang.ref.SoftReference;
SoftReference<byte[]> softCache = new SoftReference<>(loadLargeData());
byte[] data = softCache.get();
if (data == null) {
    data = loadLargeData(); // újratöltés, ha kidobták
    softCache = new SoftReference<>(data);
}

2. példa: Memóriaszivárgás statikus gyűjteményen keresztül

// ❌ MEMÓRIASZIVÁRGÁS: a statikus map korlátlanul nő
public class LeakyRegistry {
    private static final Map<String, UserSession> sessions = new HashMap<>();

    public static void register(String id, UserSession session) {
        sessions.put(id, session); // a session-ök soha nem törlődnek!
    }
    // Nincs remove() metódus → felhalmozódnak → Old Gen megtelik → Full GC → OOM
}

// ✅ Javítás: WeakReference értékek vagy explicit eviction
public class SafeRegistry {
    private static final Map<String, WeakReference<UserSession>> sessions
        = new ConcurrentHashMap<>();

    public static void register(String id, UserSession session) {
        sessions.put(id, new WeakReference<>(session));
    }

    public static UserSession get(String id) {
        WeakReference<UserSession> ref = sessions.get(id);
        return (ref != null) ? ref.get() : null;
    }
}

3. példa: GC monitorozás JMX MXBean-ekkel

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

public class GCMonitor {
    public static void printGCStats() {
        List<GarbageCollectorMXBean> gcBeans =
            ManagementFactory.getGarbageCollectorMXBeans();

        for (GarbageCollectorMXBean gc : gcBeans) {
            System.out.printf("GC neve: %s%n", gc.getName());
            System.out.printf("  Gyűjtések száma: %d%n", gc.getCollectionCount());
            System.out.printf("  Összes idő:      %d ms%n", gc.getCollectionTime());
        }
    }

    // GC értesítési listener regisztrálása (Java 7+)
    public static void registerGCListener() {
        for (GarbageCollectorMXBean gc : ManagementFactory.getGarbageCollectorMXBeans()) {
            if (gc instanceof javax.management.NotificationEmitter emitter) {
                emitter.addNotificationListener((notification, handback) -> {
                    System.out.println("GC esemény: " + notification.getType());
                }, null, null);
            }
        }
    }
}

4. példa: GC hangolási JVM flag-ek (production G1 konfiguráció)

# Production-kész G1 indítási flag-ek
java \
  -Xms8g -Xmx8g \                            # Rögzített heap — kerüli az átméretezési pause-okat
  -XX:+UseG1GC \
  -XX:MaxGCPauseMillis=150 \                  # Cél max pause
  -XX:G1HeapRegionSize=16m \                  # Nagy régiók nagy heap-hez
  -XX:InitiatingHeapOccupancyPercent=35 \     # Korábbi concurrent marking indítás
  -XX:G1ReservePercent=15 \                   # Fejléc a promóció számára
  -Xlog:gc*:file=logs/gc.log:time,uptime:filecount=10,filesize=20m \
  -XX:+HeapDumpOnOutOfMemoryError \
  -XX:HeapDumpPath=/dumps/ \
  -jar myapp.jar

# ZGC latencia-érzékeny szolgáltatásokhoz (Java 15+)
java \
  -Xms16g -Xmx16g \
  -XX:+UseZGC \
  -XX:SoftMaxHeapSize=14g \
  -Xlog:gc*:file=logs/zgc.log:time,uptime \
  -jar myapp.jar

Tipikus hiba: Finalizer-ek és GC késleltetés

// ❌ A finalizer-ek késleltetik a GC-t — az objektumoknak egy extra GC ciklust kell túlélniük
public class BadResourceWithFinalizer {
    @Override
    protected void finalize() throws Throwable {
        // Ne csináld ezt — kiszámíthatatlan, késlelteti a GC-t, feltámaszthatja az objektumot
        cleanup();
    }

    private void cleanup() { /* erőforrások felszabadítása */ }
}

// ✅ Használj try-with-resources és AutoCloseable-t helyette
public class GoodResource implements AutoCloseable {
    @Override
    public void close() {
        cleanup(); // determinisztikus, azonnal meghívódik
    }
}

// Vagy Cleaner (Java 9+) natív erőforrás-tisztításhoz finalizer hátrányai nélkül
import java.lang.ref.Cleaner;
public class CleanResource {
    private static final Cleaner cleaner = Cleaner.create();
    private final Cleaner.Cleanable cleanable;

    public CleanResource() {
        this.cleanable = cleaner.register(this, new CleanupAction());
    }

    @Override
    public void close() {
        cleanable.clean();
    }

    private static class CleanupAction implements Runnable {
        @Override public void run() { /* natív erőforrások felszabadítása */ }
    }
}

5. Trade-offok

Szempont Részletek
Teljesítmény A GC ~1–5% CPU overheadet ad. A ZGC/Shenandoah magasabb concurrent overheadet jelent, mint a Serial/Parallel, de eliminálja a hosszú pause-okat.
💾 Memória A GC fejléket igényel: a heap 70–80%-os feltöltöttség az édes pont. A túl nagy heap hosszú pause ciklusokat; a túl kis heap sűrű GC-t okoz.
🔧 Karbantarthatóság Az automatikus memóriakezelés kizárja a dangling pointer hibákat, de megköveteli a referencia típusok és a véletlen objektum-visszatartás megértését.
🔄 Rugalmasság A JVM 6 collector-t kínál. Váltás egyetlen JVM flag változtatással lehetséges — kódmódosítás nélkül.
⏱️ Latencia vs Throughput A Serial/Parallel a throughput-ot helyezi előtérbe. A G1 egyensúlyoz. A ZGC/Shenandoah a latenciát priorizálja (ultra-rövid pause-ok, némi throughput veszteséggel).
📈 Skálázhatóság A ZGC pause idők nem nőnek a heap méretével — kritikus terabájtos heap-ek esetén.

6. Gyakori hibák

1. ❌ A `-Xms` és `-Xmx` nem egyenlőre van állítva

# ❌ A JVM kis heap-pel indul, nyomás alatt növeli — GC-t vált ki az átméretezés közben
java -Xmx4g -jar app.jar

# ✅ Rögzített heap méret eliminálja az átméretezési GC-t
java -Xms4g -Xmx4g -jar app.jar

A heap átméretezés Full GC eseményeket és OS memória allokációs késleltetést okoz production-ban.


2. ❌ Memóriaszivárgás statikus gyűjteményeken keresztül

// ❌ Klasszikus szivárgás: listener/handler registry törlés nélkül
public class EventBus {
    private static final List<EventListener> listeners = new ArrayList<>();
    public static void subscribe(EventListener l) { listeners.add(l); }
    // Nincs unsubscribe() — a listener-ek (és teljes objektumgráfjuk) soha nem gyűjthetők
}

// ✅ Támogasd a deregisztrációt és használj weak reference-eket opcionális listener-ekhez
private static final List<WeakReference<EventListener>> listeners = new CopyOnWriteArrayList<>();

3. ❌ `System.gc()` használata

// ❌ Soha ne hívd production kódban
System.gc(); // Csak hint — a JVM figyelmen kívül hagyhatja. Általában Full GC-t vált ki.
             // Kiszámíthatatlan stop-the-world pause-okat okoz, anti-pattern.

// ✅ Hagyd, hogy a GC saját ütemterve szerint fusson. Bízz a hangolási flag-ekben.

4. ❌ Finalizer-ek GC késleltetést okoznak

// ❌ A finalizer-rel rendelkező objektumok KÉT GC ciklust igényelnek a gyűjtéshez:
//    1. ciklus: elérhetetlennek minősítik, finalizációs sorba kerül
//    2. ciklus: a finalize() lefut, majd az objektum gyűjtésre kerül
// Ez megduplázza a memória nyomást és telítheti a finalizer thread-et.

5. ❌ Mérés nélküli hangolás

# ❌ Véletlen flag kombinációk adat nélkül
-XX:NewRatio=2 -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=5

# ✅ Először engedélyezd a GC naplózást, elemezd, majd egyszerre egy változót hangolj
-Xlog:gc*:file=gc.log:time,uptime,level,tags
# Elemzéshez használd a GCViewer-t, GCEasy-t vagy JFR-t, mielőtt flag-eket változtatsz

7. Senior-szintű meglátások

A GC hangolás mérés-vezérelt

A leggyakoribb hiba, amit senior mérnökök látnak: GC flag-ek hangolása alap viszonyítási pontok nélkül. Engedélyezd a GC naplózást, terhelés-tesztelj staging környezetben, majd elemezd. Eszközök: Java Flight Recorder (JFR), JDK Mission Control, GCViewer, GCEasy.io.

G1 vs ZGC kiválasztási szempontok

  • Használj G1-et, ha a pause SLA-d 100–200ms és a heap 32 GB alatt van. A G1 ergonómiája jól automatikusan hangol.
  • Használj ZGC-t, ha a pause SLA < 10ms, a heap > 32 GB, vagy latencia-kritikus szolgáltatásokat futtatsz.
  • A Java 21-ben lévő ZGC (generational ZGC -XX:+ZGenerational flag-gel) tovább javítja a throughput-ot az ultra-alacsony latencia megőrzése mellett.

Safepoint-ok

A Stop-the-World GC pause-okhoz szükség van arra, hogy minden application thread elérjen egy safepoint-ot — egy ismert, biztonságos pontot a bytecode végrehajtásban. A safepoint elérése időbe telik (Time To Safepoint, TTS). A magas TTS felfújhatja a látszólagos GC pause időket. Monitor: -Xlog:safepoint.

Write barrier-ek

A concurrent GC-k (G1, ZGC, Shenandoah) write barrier-eket — a JIT által minden referencia íráshoz injektált kódot — használnak a concurrent marking során változó referenciák nyomon követésére. Ez biztosítja, hogy a GC konzisztens képet látjon az objektumgráfról. A write barrier-ek kis overheadet adnak (~1–3% throughput veszteség).

Hogyan ér el a ZGC < 10ms pause-okat

A ZGC colored pointer-eket (metaadat bitek a 64 bites pointer-ekben) és load barrier-eket (minden referencia olvasáskor futó kód) használ a relokáció párhuzamos elvégzéséhez. A thread-ek lustán javítják ki az elavult pointer-eket, ahogy hozzáférnek az objektumokhoz. Az egyetlen STW fázisok a rövid gyökér vizsgálati műveletek, amelyek a thread számmal, nem a heap mérettel skálázódnak.

Remembered Set-ek és Card Table-ek

A G1 régiónként egy Remembered Set-et tart fenn — egy nyilvántartást arról, hogy mely más régiók tartanak referenciát ebbe a régióba. Ez lehetővé teszi, hogy a G1 a régiók egy részhalmazát (a „Collection Set"-et) gyűjtse a teljes heap vizsgálata nélkül. A Card Table-ök (CMS és G1 által használt) a heap-et 512 bájtos kártyákra osztják és nyomon követik a piszkos kártyákat (az utolsó GC óta módosított) a generációk közötti referenciák hatékony megtalálásához.

TLAB — Thread-Local Allocation Buffer

Minden thread-nek van egy privát Eden darabja, amelyet TLAB-nak neveznek. Az objektum allokáció egy egyszerű pointer bump (zárolás nélkül), így a new műveletek rendkívül gyorsak. Csak akkor kell a thread-nek új TLAB-ot kérnie a megosztott Eden-ből (szinkronizációval), amikor a saját TLAB-ja kimerül.

Epsilon GC teszteléshez

Használd a -XX:+UseEpsilonGC flag-et benchmark tesztekben a GC zaj eliminálásához és a nyers allokációs throughput méréséhez. Szintén hasznos memóriaszivárgás viselkedés demonstrálásához kontrollált környezetben.


8. Szószedet

Kifejezés Definíció
Minor GC A Young Gen gyűjtése (Eden + Survivor terek); gyors, sűrű
Major GC Az Old Gen gyűjtése; lassabb, mint a Minor GC
Full GC A teljes heap gyűjtése (Young + Old + Metaspace); leghosszabb pause
Stop-the-World (STW) Minden application thread megáll, amíg a GC fut
Safepoint Kódban lévő pont, ahol a thread állapota ismert-biztonságos a GC számára
Write Barrier Referencia írásokhoz injektált kód a concurrent GC helyességének támogatásához
GC Root Garantáltan élő referencia: thread stack-ek, statikus mezők, JNI ref-ek
Remembered Set Régiónkénti készlet az abba a régióba mutató referenciákról (G1 által használt)
Card Table Heap 512 bájtos kártyákra osztva; piszkos kártyák nyomon követése a generációk közötti ref-ekhez
TLAB Thread-Local Allocation Buffer — privát Eden darab thread-enkénti gyors allokációhoz
Region A G1 GC által használt rögzített méretű heap egység (1–32 MB)
Humongous Object G1 régió 50%-ánál nagyobb objektum; közvetlenül az Old Gen-ben allokálva
Promotion Egy túlélő objektum áthelyezése a Young Gen-ből az Old Gen-be
Tenuring Öregedési mechanizmus — N Minor GC-t túlélő objektumok promótálva lesznek
Concurrent Marking GC fázis, amely az alkalmazás thread-jeivel párhuzamosan jelöli az élő objektumokat
Colored Pointer ZGC technika: metaadat 64 bites pointer-ek fel nem használt bitjeiben tárolva
Load Barrier Referencia olvasásokhoz injektált kód (ZGC) a concurrent relokáció kezeléséhez

9. Cheatsheet

  • 🗑️ GC = automatikus heap memória visszaigénylés — GC gyökerektől indul, elérhetetlen objektumokat gyűjt
  • 🧬 Generációs GC — Eden → Survivor S0/S1 → Old Gen; a legtöbb objektum Eden-ben hal meg
  • ⚙️ Az alapértelmezett GC a G1 Java 9 óta — régió-alapú, ~200ms pause cél
  • ZGC = sub-10ms pause-ok a heap méretétől függetlenül — latencia-kritikus szolgáltatásokhoz
  • 📏 Mindig állítsd a -Xms = -Xmx értéket production-ban az átméretezési GC pause-ok elkerüléséhez
  • 🔍 Mérj hangolás előtt — engedélyezd a -Xlog:gc* naplózást és elemezd JFR-rel vagy GCViewer-rel
  • 🧵 A TLAB szinte ingyen teszi a new-t — pointer bump thread-enkénti, zárolási verseny nélkül
  • 🔗 WeakReference / SoftReference — hagyd, hogy a GC szükség esetén visszaigényelje; cache-ekhez használd
  • 🚫 Soha ne hívj System.gc()-t — anti-pattern, kiszámíthatatlan Full GC-t vált ki
  • 🏷️ A safepoint-ok rejtett latenciát adnak — monitorozd a TTS-t -Xlog:safepoint-tal production-ban

🎮 Játékok

10 kérdés