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:MaxGCPauseMillissegí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:+ZGenerationalflag-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