Skip to main content

simple JVM GC guide

ยท 4 min read
Ryukato
BackEnd Software Developer

๐Ÿ“Œ 1. JVM ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ์ดํ•ดโ€‹

JVM์€ ์‹คํ–‰ ์ค‘ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฃผ์š” ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:

  • Metaspace (ํด๋ž˜์Šค ๋ฉ”ํƒ€์ •๋ณด)
  • Heap (๊ฐ์ฒด ์ธ์Šคํ„ด์Šค ์ €์žฅ)
  • Stack (์ง€์—ญ ๋ณ€์ˆ˜, ํ”„๋ ˆ์ž„ ๋“ฑ)
  • Code Cache (JIT ๊ฒฐ๊ณผ ์ €์žฅ)

  • Heap: ๋Œ€๋ถ€๋ถ„์˜ new ๊ฐ์ฒด๊ฐ€ ์ด๊ณณ์— ์ƒ์„ฑ๋จ
  • Metaspace: static ํ•„๋“œ, ํด๋ž˜์Šค ๊ตฌ์กฐ, ๋ฉ”์„œ๋“œ ์ •๋ณด ๋“ฑ ํด๋ž˜์Šค ๋กœ๋”ฉ ์‹œ ์ €์žฅ
  • Stack: ๊ฐ ์Šค๋ ˆ๋“œ๋งˆ๋‹ค ์กด์žฌ, ์ง€์—ญ ๋ณ€์ˆ˜ ๋ฐ ํ˜ธ์ถœ ์ปจํ…์ŠคํŠธ ์ €์žฅ

โ™ป๏ธ 2. GC(Garbage Collection) ๊ธฐ๋ณธ ์ฒ˜๋ฆฌ ๋‹จ๊ณ„โ€‹

  1. ๊ฐ์ฒด ์ƒ์„ฑ โ†’ Eden ์˜์—ญ์— ํ• ๋‹น
  2. Mark โ†’ GC Root๋กœ๋ถ€ํ„ฐ ๋„๋‹ฌ ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด ์ถ”์ 
  3. Sweep/Copy/Compact
    • Young GC: ์‚ด์•„๋‚จ์€ ๊ฐ์ฒด๋ฅผ Survivor ๋˜๋Š” Old๋กœ ๋ณต์‚ฌ
    • Old GC: Mark-Compact๋กœ ๋‹จํŽธํ™” ํ•ด์†Œ
  4. Promotion โ†’ ์ผ์ • ์ƒ์กด ํšŸ์ˆ˜ ์ด์ƒ ๊ฐ์ฒด๋Š” Old ์˜์—ญ์œผ๋กœ ์Šน๊ฒฉ

โš™๏ธ 3. G1 GC ๊ตฌ์กฐ ์š”์•ฝ (JDK 17 ๊ธฐ๋ณธ GC)โ€‹

  • ์ „์ฒด ํž™์„ ๊ณ ์ • ํฌ๊ธฐ Region์œผ๋กœ ๋‚˜๋ˆ” (Eden, Survivor, Old, Humongous)
  • GC ์œ ํ˜•:
    • Young GC: Eden โ†’ Survivor
    • Mixed GC: ์ผ๋ถ€ Old๋„ ์ˆ˜์ง‘
    • Full GC: ์ „์ฒด ํž™ ์ˆ˜์ง‘ (๊ฐ€๋Šฅํ•œ ํšŒํ”ผ)

๐Ÿ” G1 GC ๋กœ๊ทธ ์˜ˆ์‹œโ€‹

[2.303s][info][gc,metaspace] GC(12) Metaspace: 60293K(60736K)->60293K(60736K)
NonClass: 52643K(52864K)->52643K(52864K)
Class: 7650K(7872K)->7650K(7872K)
  • Metaspace๋Š” ํด๋ž˜์Šค ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ
  • NonClass: ๋ฉ”์„œ๋“œ, ์‹ฌ๋ณผ ๋“ฑ
  • Class: ํด๋ž˜์Šค ๊ตฌ์กฐ ์ •๋ณด

๐Ÿง  4. Metaspace ๊ด€๋ฆฌ ํŒโ€‹

  • Metaspace๋Š” ํž™์ด ์•„๋‹Œ ๋„ค์ดํ‹ฐ๋ธŒ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์‚ฌ์šฉ๋จ
  • ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฌด์ œํ•œ โ†’ -XX:MaxMetaspaceSize๋กœ ์ œํ•œ ๊ฐ€๋Šฅ
  • ๋™์  ClassLoader, SPI ์‚ฌ์šฉ ์‹œ ๋ฉ”ํƒ€์ŠคํŽ˜์ด์Šค ๋ˆ„์ˆ˜ ์œ„ํ—˜ โ†‘
-XX:MetaspaceSize=64m
-XX:MaxMetaspaceSize=256m

๐Ÿ“ฆ 5. GC์— ์œ ๋ฆฌํ•œ ๊ฐ์ฒด ๊ด€๋ฆฌ ์ „๋žตโ€‹

์ „๋žต์„ค๋ช…
์ฐธ์กฐ ํ•ด์ œobj = null ๋“ฑ์œผ๋กœ ๋ช…์‹œ์  ํ•ด์ œ
์Šค์ฝ”ํ”„ ์ถ•์†Œ๋ฉ”์„œ๋“œ ์ง€์—ญ ๋ณ€์ˆ˜, ๋ธ”๋ก ์‚ฌ์šฉ
Escape Analysis ์œ ๋„์™ธ๋ถ€๋กœ ๋…ธ์ถœ๋˜์ง€ ์•Š์œผ๋ฉด Stack ํ• ๋‹น
WeakReference ์‚ฌ์šฉ์บ์‹œ ๋“ฑ์—์„œ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ
ThreadLocal ๊ด€๋ฆฌ์‚ฌ์šฉ ํ›„ ๋ฐ˜๋“œ์‹œ .remove() ํ˜ธ์ถœ

โš ๏ธ ์ฃผ์˜: ๋žŒ๋‹ค ์บก์ฒ˜์™€ ThreadLocalโ€‹

  • ๋žŒ๋‹ค ์บก์ฒ˜ ์‹œ ์บก์ฒ˜๋œ ๊ฐ์ฒด๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ํ•„๋“œ๋กœ ์ €์žฅ๋จ โ†’ Executor ๋“ฑ์—์„œ ์ฐธ์กฐ๊ฐ€ ๋‚จ์•„ ์žˆ์œผ๋ฉด GC ์•ˆ ๋จ
  • ThreadLocal์€ Thread๊ฐ€ ์ข…๋ฃŒ๋˜๊ธฐ ์ „๊นŒ์ง€ ์ฐธ์กฐ ์œ ์ง€ โ†’ ThreadPool์—์„œ ์ฃผ์˜ ํ•„์š”
try {
threadLocal.set(value);
...
} finally {
threadLocal.remove();
}

๐Ÿ” ์ถ”์ฒœ ํˆด & ๋ช…๋ น์–ดโ€‹

  • jcmd <pid> VM.native_memory summary
  • jcmd <pid> GC.class_stats
  • -XX:+PrintGCDetails -Xlog:gc* โ†’ GC ๋กœ๊ทธ ํ™•์ธ
  • GCViewer, GCEasy.io

๐Ÿ“š ์ฐธ๊ณ  ์ž๋ฃŒโ€‹


๐Ÿ’ก JVM์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ์™€ GC ๋™์ž‘์„ ์ดํ•ดํ•˜๋ฉด, ์˜ˆ๊ธฐ์น˜ ๋ชปํ•œ ๋ฉ”๋ชจ๋ฆฌ ์ด์Šˆ๋ฅผ ์‚ฌ์ „์— ๋ฐฉ์ง€ํ•˜๊ณ ,
์„ฑ๋Šฅ ์ตœ์ ํ™”์™€ ์šด์˜ ์•ˆ์ •์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.