ํ์ฌ์ ๋๋ฃ ์ ์ ๊ฐ๋ฐ์ ๋ถ๋ค์ ์ํด ์ ๋ฆฌํ๋ค๊ฐ ๋ธ๋ก๊ทธ์๋ ์ ๋ฆฌํด๋ณด๋ฉด ์ข์ ๊ฒ ๊ฐ์ ์์ฑํ๊ฒ ๋์์ต๋๋ค. JVM(Java Virtual Machine)์์ ๊ฐ๋น์ง ์ปฌ๋ ์ (GC)์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๋์ผ๋ก ๊ด๋ฆฌํด ์ฃผ๋ ์ค์ํ ๊ธฐ๋ฅ์ ๋๋ค. ํ์ง๋ง, GC๊ฐ ์ธ์ ๊ฐ์ฒด๋ฅผ ์ ๊ฑฐํ๋์ง, ์ด๋ค ๋ฐฉ์์ผ๋ก ๋์ํ๋์ง ์ ํํ ์ดํดํ๋ ๊ฒ์ ์ฝ์ง ์์ต๋๋ค. ํนํ, Stop-the-World(STW) ํ์์ ์ฑ๋ฅ์ ํฐ ์ํฅ์ ๋ฏธ์น ์ ์๊ธฐ ๋๋ฌธ์ ์ด์ ๋ํ ์ดํด๊ฐ ํ์ํฉ๋๋ค.
์ด๋ฒ ๊ธ์์๋ GC๊ฐ ๋๋ฌ ๊ฐ๋ฅ์ฑ์ ํ๋จํ๋ ๋ฐฉ์๊ณผ ๊ฐ๋ฐ์๊ฐ ์ด๋ฅผ ์ด๋ป๊ฒ ํ์ฉํ ์ ์๋์ง๋ฅผ ์ค๋ช ํ๊ณ , Stop-the-World๋ ๋ฌด์์ด๋ฉฐ, ์ด๋ฅผ ์ต์ํํ๋ ๋ฐฉ๋ฒ๊น์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค. ๐

JVM์์ ๊ฐ๋น์ง ์ปฌ๋ ์ ์ ๋๋ฌ ๊ฐ๋ฅ์ฑ(Reachability)์ ๊ธฐ์ค์ผ๋ก ๊ฐ์ฒด๋ฅผ ์ ๋ฆฌํฉ๋๋ค. ์ฆ, ์ด๋ค ๊ฐ์ฒด๊ฐ ๋ ์ด์ ์ฌ์ฉ๋์ง ์๋๋ค๋ฉด, ํด๋น ๊ฐ์ฒด๋ GC์ ๋์์ด ๋ฉ๋๋ค.
๋ฃจํธ ์งํฉ(Root Set): JVM์ ํน์ ๊ฐ์ฒด๋ฅผ ๋ฃจํธ๋ก ์ผ๊ณ , ์ด๋ฅผ ๊ธฐ์ค์ผ๋ก ๋๋ฌ ๊ฐ๋ฅํ ๊ฐ์ฒด๋ฅผ ํ์ํฉ๋๋ค. ๋ฃจํธ ์งํฉ์๋ ๋ค์์ด ํฌํจ๋ฉ๋๋ค:
๊ฐ์ฒด ์ฐธ์กฐ ๊ทธ๋ํ ํ์: ๋ฃจํธ ์งํฉ์์๋ถํฐ ์์ํ์ฌ, ์ฐธ์กฐ๋ ๊ฐ์ฒด๋ค์ ์์ฐจ์ ์ผ๋ก ํ์ํ๋ฉฐ ๋๋ฌ ๊ฐ๋ฅํ ๊ฐ์ฒด๋ฅผ ์๋ณํฉ๋๋ค.
๋๋ฌ ๋ถ๊ฐ๋ฅ ๊ฐ์ฒด(Garbage) ์๋ณ: ๋ฃจํธ ์งํฉ์ผ๋ก๋ถํฐ ์ฐธ์กฐ๋์ง ์๋ ๊ฐ์ฒด๋ GC์ ๋์์ด ๋ฉ๋๋ค.
import java.util.ArrayList;
import java.util.List;
public class GCDemo {
static List<Object> globalList = new ArrayList<>();
public static void main(String[] args) {
Object obj1 = new Object(); // ์คํ ๋ณ์ (GC ๋์ X)
globalList.add(obj1); // static ๋ณ์์์ ์ฐธ์กฐ (GC ๋์ X)
Object obj2 = new Object(); // ์๋ก์ด ๊ฐ์ฒด ์์ฑ
obj2 = null; // GC ๋์์ด ๋จ
System.gc(); // ๊ฐ์ GC ์์ฒญ
System.out.println("GC ์คํ ์๋ฃ!");
}
}
obj1์globalList์์ ์ฐธ์กฐ๋๊ธฐ ๋๋ฌธ์ GC ๋์์ด ์๋๋๋ค. ๋ฐ๋ฉด,obj2๋ ์ฐธ์กฐ๊ฐ ์ ๊ฑฐ๋์๊ธฐ ๋๋ฌธ์ GC ๋์์ด ๋ฉ๋๋ค.
Java์์๋ java.lang.ref ํจํค์ง๋ฅผ ํ์ฉํ์ฌ GC๊ฐ ๊ฐ์ฒด๋ฅผ ์ ๋ฆฌํ๋ ๋ฐฉ์์ ์ํฅ์ ์ค ์ ์์ต๋๋ค.
import java.lang.ref.WeakReference;
public class WeakReferenceExample {
public static void main(String[] args) {
Object strongRef = new Object();
WeakReference<Object> weakRef = new WeakReference<>(strongRef);
strongRef = null; // ๊ฐํ ์ฐธ์กฐ ์ ๊ฑฐ
System.gc(); // GC ์คํ ์์ฒญ
if (weakRef.get() == null) {
System.out.println("๊ฐ์ฒด๊ฐ GC์ ์ํด ์ ๊ฑฐ๋์์ต๋๋ค.");
} else {
System.out.println("๊ฐ์ฒด๋ ์์ง ์ด์ ์์ต๋๋ค.");
}
}
}
WeakReference๋ฅผ ์ฌ์ฉํ๋ฉด GC๊ฐ ์คํ๋ ๋ ๊ฐ์ฒด๊ฐ ๋ ๋นจ๋ฆฌ ์ ๋ฆฌ๋ฉ๋๋ค.
GC๊ฐ ์คํ๋ ๋ JVM์ ์ผ์์ ์ผ๋ก ๋ชจ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ค๋ ๋๋ฅผ ๋ฉ์ถ๊ณ (GC ์ํ์ ์ํด), ํ์ํ ๊ฐ์ฒด๋ฅผ ์ ๋ฆฌํฉ๋๋ค. ์ด ํ์์ Stop-the-World(STW)๋ผ๊ณ ํฉ๋๋ค.
public class StopTheWorldDemo {
public static void main(String[] args) {
Runnable task = () -> {
while (true) {
byte[] memory = new byte[10 * 1024 * 1024]; // 10MB ํ ๋น
try {
Thread.sleep(50); // ๋ฉ๋ชจ๋ฆฌ ์ฆ๊ฐ ์๋ ์กฐ์
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread(task).start();
while (true) {
long start = System.currentTimeMillis();
System.gc(); // ๊ฐ์ GC ์คํ
long end = System.currentTimeMillis();
System.out.println("GC ์คํ ์๊ฐ: " + (end - start) + "ms");
}
}
}
์ด ์ฝ๋์์
System.gc()๋ฅผ ์คํํ๋ฉด STW๊ฐ ๋ฐ์ํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ฉ์ถ๋ ์๊ฐ์ด ์ฆ๊ฐํ ์ ์์ต๋๋ค.
JVM์ ๊ฐ๋น์ง ์ปฌ๋ ์ ์ ์ ํ๋ฆฌ์ผ์ด์ ์ฑ๋ฅ๊ณผ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ฅผ ์ํด ํ์์ ์ธ ๊ธฐ๋ฅ์ ๋๋ค. ํ์ง๋ง, Stop-the-World(STW) ํ์์ ์ต์ํํ๊ณ , GC ์ฑ๋ฅ์ ์ต์ ํํ๋ ๋ฐฉ๋ฒ์ ์ดํดํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
โ GC๋ ๋๋ฌ ๊ฐ๋ฅ์ฑ(Reachability)์ ๊ธฐ์ค์ผ๋ก ๊ฐ์ฒด๋ฅผ ์ ๋ฆฌํ๋ค.
โ SoftReference์ WeakReference๋ฅผ ํ์ฉํ๋ฉด GC ์ํฅ์ ์กฐ์ ํ ์ ์๋ค.
โ Stop-the-World(STW)๋ GC ์ํ ์ค JVM์ด ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฉ์ถ๋ ํ์์ด๋ค.
โ ์ต์ JVM์์๋ G1 GC, CMS GC, ZGC๋ฅผ ์ฌ์ฉํ์ฌ STW๋ฅผ ์ค์ผ ์ ์๋ค.
์ด์ JVM์ GC ๋์ ๋ฐฉ์๊ณผ STW๋ฅผ ์ดํดํ๊ณ , ํจ์จ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ฅผ ์ ์ฉํด ๋ณด์ธ์! ๐