9148c358d0
Topic_Agent/Topic_Blog/Topics/Topics_Biz/Topics_Meeting/Topics_Rag의 마크다운 지식 문서를 Topic_General/Topic_Programming/Topic_Graphic/Topic_Business 4개 카테고리로 재분류. - 중복 제거: frontmatter의 status:duplicate/merged + duplicate_of/redirect_to 필드로 자기 자신을 중복으로 선언한 리다이렉트 stub 1032개 제거, 완전 동일 내용 파일 472개 제거, 동일 파일명·다른 내용 충돌 시 더 큰(완전한) 버전만 유지(162개 제거) — 총 1639개 중복 제거. - 분류: 폴더 단위로 명확한 항목(AI_and_ML/Coding/Architecture 등 → Programming, Comfyui/Visual_Effects → Graphic, Topics_Biz/Topics_Meeting/사업 등 → Business, Poetic_Blog_Writing/창의성/Game_Design 등 → General)은 폴더 우선순위로, 나머지 혼재 폴더(Topic_Agent/Topic_Blog/Topics 루트/Thinking & Reasoning/Other/UI_UX_Assets)는 title/tags 키워드 스코어링으로 파일 단위 분류(불명확한 경우 General로 폴백). 원본 폴더명은 "From_*" 서브폴더로 보존해 추적 가능성 유지. - 최종 배치: Programming 2784 / General 1608 / Graphic 285 / Business 249 = 4926개 문서. - 에이전트 운영 상태(.astra/.agent/.obsidian/sessions/memory/_company/docs/lessons/_shared/src)는 지식 콘텐츠가 아니므로 재분류 대상에서 제외하고 원위치 유지. - Topics/Topic_email(상위 보호 폴더 Topic_email과 파일명 100% 중복) 삭제 — 보호 폴더 자체는 미변경. - 완전히 비게 된 Topic_Agent/Topic_Blog/Topics_Biz/Topics_Rag 폴더 제거.
6.0 KiB
6.0 KiB
id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
| id | title | category | status | canonical_id | aliases | duplicate_of | source_trust_level | confidence_score | verification_status | tags | raw_sources | last_reinforced | github_commit | tech_stack | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| wiki-2026-0508-gc-root | GC Root | 10_Wiki/Topics | verified | self |
|
none | A | 0.9 | applied |
|
2026-05-10 | pending |
|
GC Root
매 한 줄
"매 도달 가능성(reachability) 의 출발점". GC Root 는 garbage collector 가 live object 를 판별하기 위해 traversal 을 시작하는 reference set. 매 root 에서 도달 불가능한 object 는 collectible 로 marking 된다. JVM, .NET CLR, V8, Go runtime 모두 같은 개념을 공유한다.
매 핵심
매 GC Root 종류 (HotSpot 기준)
- Stack reference: 매 thread 의 local variable / parameter / operand stack.
- Static field: 매 loaded class 의 static reference.
- JNI local/global: 매 native code 가 hold 한 reference.
- Active thread: 매 살아있는
Threadobject 자체. - Class metadata: 매 ClassLoader, Class object (Metaspace).
- Synchronization monitor: 매
synchronized로 lock 된 object. - Weak/Soft/Phantom 제외: 매 reachability 약한 reference 는 root 가 아님.
매 Reachability tier
- Strongly reachable: root 에서 strong ref 만으로 도달 → never collected.
- Softly reachable: SoftReference 로만 도달 → 매 memory pressure 시 collect.
- Weakly reachable: WeakReference 만 → 매 next GC cycle 에 collect.
- Phantom reachable: PhantomReference → enqueue 후 cleaning.
- Unreachable: → collectible.
매 응용
- Memory leak 진단 (heap dump → root path 추적).
- Escape analysis (root 도달 안 되는 local → stack alloc).
- Concurrent GC 의 root scanning (ZGC, Shenandoah, G1 의 phase 1).
💻 패턴
1. Heap dump 에서 root path 찾기 (Eclipse MAT / jhat)
# JVM heap dump 생성
jcmd <pid> GC.heap_dump /tmp/heap.hprof
# Eclipse MAT CLI 로 leak suspects 분석
./MemoryAnalyzer -consoleLog -application org.eclipse.mat.api.parse \
/tmp/heap.hprof org.eclipse.mat.api:suspects
2. JFR 로 GC root 통계 수집 (JDK 21+)
java -XX:StartFlightRecording=duration=60s,filename=app.jfr,settings=profile \
-XX:+UseZGC -Xmx4g -jar app.jar
jfr print --events GarbageCollection,GCReferenceStatistics app.jfr
3. WeakReference 로 root 진입 회피
import java.lang.ref.WeakReference;
import java.util.WeakHashMap;
// Cache 가 GC root 가 되어 leak 발생하는 anti-pattern 회피
public class Cache<K, V> {
private final WeakHashMap<K, V> map = new WeakHashMap<>();
public void put(K key, V value) { map.put(key, value); }
public V get(K key) { return map.get(key); }
// key 가 외부에서 strong ref 사라지면 entry 자동 제거
}
4. ThreadLocal leak 회피 (매 typical root leak)
public class RequestContext {
private static final ThreadLocal<UserSession> CTX = new ThreadLocal<>();
public static void set(UserSession s) { CTX.set(s); }
public static UserSession get() { return CTX.get(); }
// 매 critical: thread pool 환경에서 반드시 remove() 호출
public static void clear() { CTX.remove(); }
}
// Servlet filter 에서:
try {
RequestContext.set(session);
chain.doFilter(req, res);
} finally {
RequestContext.clear(); // 매 root reference 끊기
}
5. JNI global ref 정리 (native code 가 GC root)
// JNI: global ref 는 명시적으로 free 해야 함
jobject globalRef = (*env)->NewGlobalRef(env, localObj);
// ... 사용 ...
(*env)->DeleteGlobalRef(env, globalRef); // 매 빠뜨리면 영구 leak
6. Static field 로 의도된 long-lived root
object AppMetrics { // 매 Kotlin object → static singleton → GC root
private val counter = AtomicLong(0)
fun increment() = counter.incrementAndGet()
fun snapshot() = counter.get()
}
7. ZGC / Shenandoah concurrent root scanning 활성화
# JDK 21+: ZGC generational
java -XX:+UseZGC -XX:+ZGenerational \
-XX:SoftMaxHeapSize=8g -Xmx16g -jar app.jar
# Shenandoah
java -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational -jar app.jar
8. Async profiler 로 allocation root 찾기
./profiler.sh -e alloc -d 60 -f alloc.html <pid>
# 매 flamegraph 에서 root → leaking site path 시각화
매 결정 기준
| 상황 | Approach |
|---|---|
| Long-lived cache | WeakHashMap / Caffeine weakKeys() |
| Per-request state in pool | ThreadLocal + try/finally remove() |
| Native handle wrapping | Cleaner (java.lang.ref.Cleaner, JDK 9+) |
| Listener registration | WeakReference 로 listener wrap |
| 매 short-lived burst alloc | 매 그냥 strong ref + young gen 의존 |
기본값: 매 strong ref + escape analysis 신뢰. WeakReference 는 매 진짜 leak 패턴 (cache, listener, ThreadLocal in pool) 에만.
🔗 Graph
- 부모: Garbage Collection
- 응용: Memory Leak Detection
🤖 LLM 활용
언제: heap dump 의 leak suspect 해석, root path 의 의미 설명, ThreadLocal/static leak pattern detection. 언제 X: 매 production 의 실제 GC tuning (real profiling 데이터 없이 추측 X).
❌ 안티패턴
- Static collection 무한 grow:
static List에 매 add 만 하고 remove 안 함 → 영구 root. - ThreadLocal in pool no remove: 매 thread 재사용 시 이전 request data 가 root 로 남음.
- JNI GlobalRef leak: native 에서
DeleteGlobalRef누락. - Anonymous inner class capture:
new Runnable() {}가 outerthis를 capture → outer 가 root 에 매달림. - Listener 등록 후 unregister 안 함: 매 EventBus, Observer 패턴의 classic leak.
🧪 검증 / 중복
- Verified (OpenJDK HotSpot source, JEP 376/439, Eclipse MAT docs).
- 신뢰도 A.
🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — GC root taxonomy + leak 진단 패턴 |