๐ JAVA 03 - JVM GC์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ
JVM GC์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ
ํ์ต ๋ชฉํ
์ด๋ฒ ์ฃผ์ ์ ํต์ฌ์ ๋จ์ํ:
โGC๋ ์ ์ฐ๋ ๊ฐ์ฒด๋ฅผ ์ ๊ฑฐํ๋ ๊ธฐ๋ฅโ
์์ค์ด ์๋๋ค.
์ค๋ฌด์์๋ ๋ค์์ ์ดํดํด์ผ ํ๋ค.
์ GC๊ฐ ํ์ํ๊ฐ?
JVM์ ์ Heap์ ์ธ๋๋ณ๋ก ๋๋๋๊ฐ?
Minor GC์ Major GC ์ฐจ์ด๋ ๋ฌด์์ธ๊ฐ?
Stop-The-World๋ ์ ๋ฐ์ํ๋๊ฐ?
G1GC๋ ์ ๋ฑ์ฅํ๋๊ฐ?
๋ฉ๋ชจ๋ฆฌ ๋์๋ ์ ๋ฐ์ํ๋๊ฐ?
์ด์ ํ๊ฒฝ์์ GC๋ ์ด๋ป๊ฒ ์ฅ์ ๊ฐ ๋๋๊ฐ?
์ฆ:
โJava ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ์์คํ ์ ์ฒดโ
๋ฅผ ์ดํดํ๋ ๊ฒ์ด ๋ชฉํ๋ค.
JVM ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ ๋ณต์ต
flowchart TD
A[JVM Memory]
A --> B[Heap]
A --> C[Stack]
A --> D[Method Area]
A --> E[Native Memory]
์ด๋ฒ ํต์ฌ์ Heap ์์ญ์ด๋ค.
Heap ๊ตฌ์กฐ
Heap์ ๊ฐ์ฒด ์ ์ฅ ์์ญ์ด๋ค.
flowchart LR
A[Heap]
A --> B[Young Generation]
A --> C[Old Generation]
์ Heap์ ๋๋ด๋๊ฐ?
ํต์ฌ ์ด์ :
โ๋๋ถ๋ถ ๊ฐ์ฒด๋ ๊ธ๋ฐฉ ์ฃฝ๋๋คโ
๋ผ๋ ๊ฒฝํ์ ํต๊ณ ๋๋ฌธ์ด๋ค.
์:
HTTP Request ๊ฐ์ฒด
DTO
StringBuilder
์์ Collection
๋๋ถ๋ถ ์์ฒญ ์ฒ๋ฆฌ ํ ๋ฐ๋ก ์ ๊ฑฐ๋๋ค.
์ฆ:
์งง๊ฒ ์ฌ๋ ๊ฐ์ฒด์ ์ค๋ ์ฌ๋ ๊ฐ์ฒด๋ฅผ ๋ถ๋ฆฌํ๋ฉด GC ํจ์จ์ด ์ฌ๋ผ๊ฐ๋ค.
Young Generation ๊ตฌ์กฐ
flowchart LR
A[Eden]
B[Survivor 0]
C[Survivor 1]
A --> B
A --> C
๊ฐ์ฒด ์์ฑ ํ๋ฆ
flowchart TD
A[๊ฐ์ฒด ์์ฑ]
--> B[Eden ์ ์ฅ]
B --> C{GC ๋ฐ์}
C -->|์ด์์์| D[Survivor ์ด๋]
C -->|์ฃฝ์| E[๋ฉ๋ชจ๋ฆฌ ์ ๊ฑฐ]
D --> F{์ค๋ ์ด์๋จ์?}
F -->|YES| G[Old Generation ์ด๋]
Minor GC
Young Generation ๋์์ผ๋ก ์ํ.
ํน์ง:
๋น ๋ฆ
์์ฃผ ๋ฐ์
๋๋ถ๋ถ ๊ฐ์ฒด ์ ๊ฑฐ ๊ฐ๋ฅ
์ ๋น ๋ฅผ๊น?
๋๋ถ๋ถ ๊ฐ์ฒด๊ฐ ์ด๋ฏธ ์ฃฝ์ด์๊ธฐ ๋๋ฌธ
์ด๋ค.
Stop-The-World(STW)
GC ์ JVM์ ์ ํ๋ฆฌ์ผ์ด์ Thread๋ฅผ ๋ฉ์ถ๋ค.
sequenceDiagram
Application->>JVM: ๊ฐ์ฒด ์ฌ์ฉ ์ค
JVM->>All Threads: Stop-The-World
JVM->>Heap: GC ์ํ
JVM->>All Threads: Resume
์ ๋ฉ์ถฐ์ผ ํ๋๊ฐ?
GC๋:
โํ์ฌ ์ด๋ค ๊ฐ์ฒด๊ฐ ์ด์์๋๊ฐ?โ
๋ฅผ ์ ํํ ์์์ผ ํ๋ค.
๊ทธ๋ฐ๋ฐ Thread๊ฐ ๊ณ์ ๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝํ๋ฉด:
์ฐธ์กฐ ๊ด๊ณ ๋ณ๊ฒฝ
๊ฐ์ฒด ์์ฑ
๊ฐ์ฒด ์ญ์
๊ฐ ๊ณ์ ๋ฐ์ํ๋ค.
์ฆ:
๋ฉ๋ชจ๋ฆฌ ์ํ๊ฐ ๊ณ์ ๋ฐ๋๋ค.
๊ทธ๋์ ์์ ํ ๋ถ์์ ์ํด ์ ์ ๋ฉ์ถ๋ค.
์ค๋ฌด์์ STW๊ฐ ์ํํ ์ด์
์:
API ์๋ต ์ง์ฐ
Timeout ์ฆ๊ฐ
TPS ๊ฐ์
์ฅ์ ์ ํ
ํนํ ๋์ฉ๋ ์๋น์ค์์:
1
STW 5์ด
๊ฐ์ ์ํฉ์ ์น๋ช ์ ์ด๋ค.
Old Generation
์ค๋ ์ด์๋จ์ ๊ฐ์ฒด ์ ์ฅ ์์ญ.
๋ํ:
Cache
Singleton Bean
Session
์ฅ๊ธฐ ์ ์ง Collection
Major GC / Full GC
Old Generation ๋์ GC.
ํน์ง:
๋๋ฆผ
STW ๊ธธ์ด์ง
์์คํ ์ํฅ ํผ
์ ๋๋ฆฐ๊ฐ?
Old ์์ญ ๊ฐ์ฒด๋:
ํฌ๊ณ
์ฐธ์กฐ ๊ด๊ณ ๋ณต์กํ๊ณ
์ด์์๋ ๊ฐ์ฒด ๋น์จ ๋๋ค
์ฆ:
GC ํ์ ๋น์ฉ์ด ๋งค์ฐ ์ปค์ง๋ค.
์ค์ ์ด์ ์ฅ์ ์ฌ๋ก
1
2
3
4
Full GC ๋ฐ์
โ STW 10์ด
โ API Timeout
โ ์ฅ์ ์ ํ
์ค์ ํ์ ์์ ๋งค์ฐ ํํ ์ฅ์ ํจํด์ด๋ค.
G1GC ๋ฑ์ฅ ๋ฐฐ๊ฒฝ
๊ธฐ์กด GC ๋ฌธ์ :
Heap ์ปค์ง์๋ก Full GC ๊ธธ์ด์ง
์์ธก ๋ถ๊ฐ๋ฅํ STW
์ด๋ฅผ ํด๊ฒฐํ๋ ค๊ณ ๋ฑ์ฅ.
G1GC ๊ตฌ์กฐ
Heap์ Region ๋จ์๋ก ๋๋๋ค.
flowchart TD
A[Heap]
A --> B[Region 1]
A --> C[Region 2]
A --> D[Region 3]
A --> E[Region N]
์ ์ข์๊ฐ?
๊ธฐ์กด:
Heap ์ ์ฒด GC
G1GC:
ํ์ํ Region ์ฐ์ GC
์ฆ:
pause time ์์ธก ๊ฐ๋ฅ
๋์ฉ๋ Heap ๋์ ๊ฐ๋ฅ
G1GC ํต์ฌ ์ฒ ํ
โGC Throughputโ๋ณด๋ค
โPause Time ์ ์ดโ
๋ฅผ ๋ ์ค์ํ๊ฒ ๋ณธ๋ค.
์ค๋ฌด์์ ์ด๊ฒ ๋งค์ฐ ์ค์ํ๋ค.
์๋๋ฉด:
์ฌ์ฉ์๋ TPS๋ณด๋ค:
์๋ต ์ง์ฐ(latency)
์ ๋ฏผ๊ฐํ๊ธฐ ๋๋ฌธ์ด๋ค.
GC Root
GC๋ ๊ฐ์ฒด ์์กด ์ฌ๋ถ๋ฅผ:
โGC Root์์ ๋๋ฌ ๊ฐ๋ฅํ๊ฐ?โ
๋ก ํ๋จํ๋ค.
๋ํ GC Root:
Stack ์ง์ญ ๋ณ์
static ๋ณ์
Thread
JNI ์ฐธ์กฐ
๋ฉ๋ชจ๋ฆฌ ๋์(Memory Leak)
Java๋ ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ๋ฐ์ํ๋ค.
๋ง์ด ์คํดํ๋ ๋ถ๋ถ์ด๋ค.
์ ๋ฐ์ํ๋๊ฐ?
Java์์ leak์:
โ์ฌ์ฉ ์ ํ์ง๋ง ์ฐธ์กฐ๊ฐ ๋จ์์๋ ๊ฐ์ฒดโ
๋ค.
์ฆ:
GC ๋์์ด ์ ๋๋ค.
๋ํ ์ฌ๋ก
1. static Collection
1
2
private static List<Object> cache =
new ArrayList<>();
๊ณ์ ์ถ๊ฐ๋ง ํ๋ฉด ์์ํ ์ด์์๋ค.
2. ThreadLocal Leak
์ค๋ฌด ๋จ๊ณจ.
1
2
ThreadLocal<User> local =
new ThreadLocal<>();
remove() ์ ํ๋ฉด Thread Pool ํ๊ฒฝ์์ ๋์ ๊ฐ๋ฅ.
3. Cache ๋ฌดํ ์ฆ๊ฐ
1
Map<String, Object> cache
eviction ์์ผ๋ฉด ์ํ.
์ด์์์ ์ค์ํ GC ๋ก๊ทธ
์ค๋ฌด์์๋ GC ๋ก๊ทธ๋ฅผ ๋ฐ๋์ ๋ณธ๋ค.
๋ํ ํ์ธ ํญ๋ชฉ:
STW ์๊ฐ
Young GC ๋น๋
Full GC ๋น๋
Heap ์ฌ์ฉ๋
Promotion ์คํจ
์์ ๋ก๊ทธ
1
2
Pause Young (G1 Evacuation Pause)
35ms
์ฑ๋ฅ ๊ด์
GC ํต์ฌ ๋ชฉํ:
Throughput
Latency
Memory Footprint
์ด ์ ์ Trade-off ๊ด๊ณ๋ค.
Trade-off
Heap ํฌ๊ฒ ์ค์
์ฅ์ :
- GC ๋น๋ ๊ฐ์
๋จ์ :
- Full GC ๊ธธ์ด์ง
Heap ์๊ฒ ์ค์
์ฅ์ :
- pause ์งง์
๋จ์ :
- GC ์์ฃผ ๋ฐ์
G1GC ์ฌ์ฉ
์ฅ์ :
- pause ์์ธก ๊ฐ๋ฅ
๋จ์ :
- CPU ์ฌ์ฉ๋ ์ฆ๊ฐ ๊ฐ๋ฅ
์์ฃผ ๋ฐ์ํ๋ ์ค์
1. Heap๋ง ๋ฌด์กฐ๊ฑด ํฌ๊ฒ ์ค์
์ด์ ์ฅ์ ์์ธ ๊ฐ๋ฅ.
2. Cache ๋ฌดํ ์ฆ๊ฐ
๋งค์ฐ ํํจ.
3. ThreadLocal remove ๋๋ฝ
์ค๋ฌด ๋จ๊ณจ ์ฅ์ .
4. Full GC ๋ฌด์
์ฅ์ ์ ์กฐ ์ ํธ ๋์นจ.
๋ฉด์ ๊ผฌ๋ฆฌ ์ง๋ฌธ
Q1. ์ Young/Old ์์ญ์ ๋๋๋๊ฐ?
ํต์ฌ:
๋๋ถ๋ถ ๊ฐ์ฒด๋ ๋นจ๋ฆฌ ์ฃฝ๊ธฐ ๋๋ฌธ
Q2. Stop-The-World๋ ์ ํ์ํ๊ฐ?
ํต์ฌ:
๊ฐ์ฒด ์ฐธ์กฐ ์์ ์ฑ ํ๋ณด
GC ์ ํ์ฑ ๋ณด์ฅ
Q3. Full GC๊ฐ ์ํํ ์ด์ ๋?
ํต์ฌ:
๊ธด STW
์๋น์ค ์๋ต ์ง์ฐ
์ฅ์ ์ ํ
Q4. Java๋ ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ๋ฐ์ํ๋๊ฐ?
ํต์ฌ:
์ฐธ์กฐ๊ฐ ๋จ์์์ผ๋ฉด GC๋์ง ์๋๋ค.
Q5. G1GC๋ ์ ๋ฑ์ฅํ๋๊ฐ?
ํต์ฌ:
๋์ฉ๋ Heap ๋์
Pause Time ์์ธก ๊ฐ๋ฅ์ฑ ํ๋ณด
์ข์ ๋ต๋ณ ์์
JVM์ ๊ฐ์ฒด ์๋ช ํน์ฑ์ ์ด์ฉํ๊ธฐ ์ํด Heap์ Young/Old ์์ญ์ผ๋ก ๋ถ๋ฆฌํฉ๋๋ค.
๋๋ถ๋ถ ๊ฐ์ฒด๋ ๋น ๋ฅด๊ฒ ์ ๊ฑฐ๋๋ฏ๋ก Young GC๋ ๋งค์ฐ ํจ์จ์ ์ ๋๋ค.
๋ฐ๋ฉด Old ์์ญ GC๋ STW ์๊ฐ์ด ๊ธธ์ด ์ค์ ์ด์ ์ฅ์ ์์ธ์ด ๋ ์ ์์ต๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด G1GC ๊ฐ์ Region ๊ธฐ๋ฐ GC๊ฐ ๋ฑ์ฅํ์ผ๋ฉฐ, ์ต๊ทผ JVM์ Throughput๋ณด๋ค Latency ์์ ์ฑ์ ์ค์ํ๊ฒ ๋ณด๋ ๋ฐฉํฅ์ผ๋ก ๋ฐ์ ํ๊ณ ์์ต๋๋ค.
๊ด๋ จ CS ๊ฐ๋ ์ฐ๊ฒฐ
Garbage Collection
Reachability Analysis
Memory Management
Runtime System
Stop-The-World
Latency vs Throughput
Generational Hypothesis
ํ์ ์์ ํนํ ์ค์ํ ํฌ์ธํธ
1. GC๋ ์ด์ ์ฅ์ ์์ธ์ด๋ค
๋จ์ CS ์ด๋ก ์ด ์๋๋ค.
2. Full GC๋ ๋ฐ๋์ ์ถ์ ํด์ผ ํ๋ค
์ฅ์ ์ ์กฐ์ผ ๊ฐ๋ฅ์ฑ ๋๋ค.
3. ThreadLocal Leak ๋งค์ฐ ํํ๋ค
ํนํ Spring + Thread Pool ํ๊ฒฝ.
4. Latency ๊ด์ ์ด ์ค์ํ๋ค
์ค๋ฌด๋ TPS๋ณด๋ค ์๋ต ์ง์ฐ์ด ์ค์ํ ๋ ๋ง๋ค.
ํต์ฌ ์์ฝ
JVM์ ๊ฐ์ฒด ์๋ช ํน์ฑ์ ์ด์ฉํด ์ธ๋๋ณ GC ์ํ
Minor GC๋ ๋น ๋ฅด๊ณ Major GC๋ ์ํํ๋ค
Stop-The-World๋ GC ์ ํ์ฑ์ ์ํ ๊ตฌ์กฐ
G1GC๋ Pause Time ์ ์ด๋ฅผ ์ํด ๋ฑ์ฅ
Java๋ ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ๋ฐ์ํ๋ค
GC๋ ์ค์ ์ด์ ์ฅ์ ์ ๋งค์ฐ ๋ฐ์ ํ๋ค
์ค๋ฌด์์๋ GC ๋ก๊ทธ ๋ถ์ ๋ฅ๋ ฅ์ด ์ค์ํ๋ค