2-2 ๋ค ์ด ๊ฐ์ฒด์ฐธ์กฐ๋ฅผ ํด์ ํ๋ผ.
by JiwonDev๋ฉ๋ชจ๋ฆฌ ๋์๋ ๊ฒ์ผ๋ก ์ ๋๋ฌ๋์ง ์๋๋ค.
์ค๋๋ ์์คํ ์์๋ ์ฝ๋๋ฆฌ๋ทฐ, ํํ๋กํ์ผ๋ฌ ๋ฆฌ๋ทฐ๋ฅผ ํ๋ค๋ณด๋ฉด ํ์์๋ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์๋ ๊ฐ ์ ๋ณตํ๋ ๊ฒฝ์ฐ๋ ํํ๋ค.
# ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ง์ ๊ด๋ฆฌํ๋ ํด๋์ค๋ผ๋ฉด ๋์์ ์ฃผ์ํ๋ผ. (Stack, Array ๋ฑ)
์๋ ์ฝ๋์์ ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ์ฌํ๊ฒ ๋ฐ์ํ๊ณ ์๋ค. ์ด๋์ธ์ง ์ฝ๊ฒ ์ฐพ์ ์ ์๋๊ฐ?
// "๋ฉ๋ชจ๋ฆฌ ๋์(memory leak)"๊ฐ ์ด๋์ ์๊ธฐ๋์ง ๋ณด์ด๋๊ฐ? public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { if (size == 0) throw new EmptyStackException(); return elements[--size]; } if (elements.length == size) // ๊ณต๊ฐ์ด ๋ถ์กฑํ๋ค๋ฉด ์คํ ํฌ๊ธฐ๋ฅผ 2๋ฐฐ์ฉ ๋๋ฆฐ๋ค. elements = Arrays.copyOf(elements, 2 * size + 1); }
๋ฐ๋ก element[--size] ์ด๋ค. ๋์ด์ ์ฌ์ฉํ์ง ์๋ ๋ฉ๋ชจ๋ฆฌ์ธ๋ฐ๋ ์ฐธ์กฐ๋ ๊ทธ๋๋ก ์ ์ง๋๊ณ ์๋ค.
์๋ฐ์ ๊ฐ๋น์ง์ปฌ๋ ํฐ(GC)๋ ์ฐธ์กฐ์ฌ๋ถ๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ ํด์ ํ๋ค. ์ฌ์ฉํ์ง๋ ์๋ ๊ณณ์์ ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ๋ฐ์ํ๋ ๊ฒ์ด๋ค. ์์ ์์ ๋ ๊ทธ๋๋ง ๋์๋ฅผ ์ฐพ๊ธฐ ์ฌ์ดํธ์ด๋ค. ์บ์ (key-value)๋ ๋ฆฌ์ค๋์ ์ฝ๋ฐฑ(callback)์ ์ฌ์ฉํ ๋ ์์ ๊ฐ์ ๋ฌธ์ ๊ฐ ์์ฃผ ๋ฐ์ํ๋ค๊ณ ์๊ฐํ๋ฉด ๋์ฐํ๋ค.
map.put(key1, "test a"); map.put(key2, "test b"); key1 = null; /* ... ๋ค๋ฅธ ์ฝ๋ ... */ // ์๋น์ค์์๋ ์ฌ์ฉ๋์ง ์์ง๋ง map์ ์๋ key1์ ๋ฐ์ดํฐ์ ์ฐธ์กฐ๋ ๊ณ์ ๋จ์์๋ค.
๋ํ JVM์ GC๊ฐ ์ด๋ฌํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฐพ์์ ํ ๋น ํด์ ํด์ค๋ค๊ณ ํ๋ค, ํฐ ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์๋ค.
GC์์๋ ํฌ๊ฒ Young ์์ญ๊ณผ Old ์์ญ์ด ์กด์ฌํ๋๋ฐ, ์ด๋ฐ์์ผ๋ก ๊ณ์ํด์ ์ฐธ์กฐํ๊ณ ์๋ ๋ฉ๋ชจ๋ฆฌ๋ Old ์์ญ๊น์ง ์ฎ๊ฒจ์ง๊ฒ ๋๊ณ Old ์์ญ์ ์์ธ ๋ฉ๋ชจ๋ฆฌ๋ ํ๋ก๊ทธ๋จ ๊ตฌ๋์ ์ ๊น ๋ฉ์ถฐ๋ฒ๋ฆฌ๊ณ (Stop-the-World) ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ํด์ ํ๋ค.
(G1GC ์ด์ ์๋) ์๋ฒ์ปดํจํฐ์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์๋์ปค์, Old ์์ญ์ ์ด๋ฌํ ๋ฐ์ดํฐ๊ฐ ์์ด๊ฒ๋๋ค๋ฉด JVM์ GC๊ฐ Old ์์ญ์ ๋น์ฐ๊ธฐ ์ํด์ ์๋ฒ๊ฐ 2~3๋ถ๊ฐ ๋ฉ์ถฐ๋ฒ๋ฆด ์ ์๋ค. ์ฅ์ ๊ฐ ๋๊ฒ๋, ๋ก์ง์ ์ค๋ฅ๊ฐ ์๋ ๊ฒ๋ ์๋๋ฐ ๋ง์ด๋ค.
# ํด๊ฒฐ์ฑ
๊ฐ๋จํ๋ค. ๋ค์ด ๊ฐ์ฒด๋ ์ฐธ์กฐ๋ฅผ ํด์ ํด์ฃผ๋ฉด ๋๋ค.
public Object pop() { if (size == 0) throw new EmptyStackException(); Object results = elements[--size]; elements[size] = null; // ๋ง๊ธฐ ์ฐธ์กฐ ์ ๊ฑฐ return results; }
๋ค๋ง ์์ ๊ฐ์ด null์ ์ฌ์ฉํ๋ ๊ฑด NullPointException ๋๋ฌธ์ ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ๋ ์๊ฒจ๋ฒ๋ฆฐ๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ ์๋ฐ์๋ Weak ์๋ฃํ (WeakHashMap)๋ฑ์ ์ ๊ณตํด์ค๋ค. ๊ธฐ์กด์ ์๋ฃํ๊ณผ ์ฌ์ฉ๋ฒ์ ๋์ผํ๋ ๊ฐ์ ์ง์ ์ฐธ์กฐํ๋๊ฒ ์๋๋ผ ์ฐธ์กฐ ๊ฐ์ฒด(WeakReference)๋ฅผ ํตํด ๊ฐ์ง๊ณ ์๋ค๊ฐ ํด๋น ๊ฐ์ด ๋ ์ด์ ์ฌ์ฉ๋์ง ์๋๋ค๊ณ ํ๋จํ๋ฉด (prime == null์ด ๋๋ค๋ฉด) ํด๋น ์์๋ฅผ ์ ๊ฑฐํ๊ณ GCํด๋ฒ๋ฆฐ๋ค.
- Weak ์๋ฃํ์ ๊ธฐ์กด์ ์๋ฃํ๊ณผ ๋๊ฐ์ด ๋ฉํฐ์ค๋ ๋์ ์์ ํ์ง ์๋ค.
- Weak ์๋ฃํ์ ๊ฑฐ์น์ง ์๊ณ , Key๋ฅผ ์ง์ ์ฐธ์กฐํด๋ฒ๋ฆฌ๋ฉด ์๋ฌด๋ฐ ์๋ฏธ๊ฐ ์์ด์ง๋ค. WeakReference๋ก ์ฐธ์กฐํด์ผํ๋ค.
public class WeakHashMapTest { public static void main(String[] args) { WeakHashMap<Integer, String> map = new WeakHashMap<>(); Integer key1 = 1000; Integer key2 = 2000; map.put(key1, "test a"); map.put(key2, "test b"); key1 = null; // map์์๋ ์ญ์ ๋ ๊ฒ์ด ์๋๋ค. ํด๋น ๋ฉ๋ชจ๋ฆฌ๊ฐ ๊ทธ๋๋ก ์ ์ง๋์ด์๋ค. // ํ์ง๋ง WeakReference ์ prime = null์ด ๋์๋๋ค. // ์ฆ GC๊ฐ ๋ฐ์ํ ๋ ํด๋น ์์์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ญ์ ๋๋ค. } }
# ๊ฐ์ฒด์ ๊ธฐ๋ณธ ์ข ๋ฃ์ (finalizer, Cleaner)๋ฅผ ์ฌ์ฉํ์ง ๋ง๋ผ
Java 9 ์ดํ ์์ด์ง ๋ฉ์๋๋ผ ๋ชจ๋ฅผ ์ ์์ง๋ง ์๋ฐ์ Object ๊ฐ์ฒด์๋ finalizer()๊ฐ ์กด์ฌํ์๋ค.
์ด๋ฅผ ํธ์ถํ๋ค๊ณ ํด์ ๋ฐ๋ก ์ญ์ ๋๋ ๊ฒ๋์๋๊ณ , Lock์ด ๊ฑธ๋ ค ํ๋ก๊ทธ๋จ ์ ์ฒด๊ฐ ๋ธ๋ญ๋ ์ ์๋ ์น๋ช ์ ์ธ ๋ฉ์๋์๋ค.
@Override public void finalize() { // ... }
Java 9 ์ดํ์๋ Cleaner ๊ฐ ์๋ฉธ์๋ก ๋์ ๋์์ผ๋ฉฐ, ๋ณดํต AutoCloseable ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํด์ ๋ฑ๋ก๋ ์ค๋ ๋์ ์ ์๋ ํด๋ฆฐ ์์ ์ ์ํํ๋ค. ์ด๋ฅผ ํตํด try-with-resource ๋ฌธ์ ๋์์ ์ง์ ๊ตฌํํ ์ ์๋ค.
try(Worker worker = new Worker()) { worker.work(); } catch(...) { }
public class CleaningRequiredObject implements AutoCloseable { private static final Cleaner cleaner = Cleaner.createโ(); private static class CleanData implements Runnable { @Override public void run() { // ์ฌ๊ธฐ์ ํด๋ฆฐ ์์
์ํ } } private final CleanData; private final Cleaner.Cleanable cleanable public CleaningRequiredObject() { this.cleanData = new CleanData(); // cleanable ๋ฑ๋ก this.cleanable = cleaner.register(this, state); } @Override public void close() { cleanable.clean(); } }
ํ์ง๋ง DB Connector๋ฅผ ์ง์ ๊ตฌํํ๋ ์์ค์ด ์๋๋ผ๋ฉด, ๋ณดํต์ ์ฌ์ฉํ ์ผ์ด ๊ฑฐ์ ์๋ค.
Java9์ Cleaner๋ฅผ ์ฌ์ฉํ๋ค๊ณ ํ๋ค ์ฑ๋ฅ์ ๋ฌธ์ ๊ฐ ๋ง๊ณ , ๊ฐ์ฒด ์ง๋ ฌํ(Serialize)๋ฅผ ํตํ ๋ณด์์ ์ธ ๋ฌธ์ ์ ์ํ ์์ ์ ๋ณด์ฅํด์ฃผ์ง ์๋๋ค๋ ๊ฑด ์ฌ์ ํ ๋๊ฐ๋ค. ์ ๋ง ํ์ํ ๊ฒฝ์ฐ (๋ค์ดํฐ๋ธ ๋ฉ์๋ - JNI๋ฅผ ์ง์ ๊ตฌํ)๊ฐ ์๋๋ผ๋ฉด ์ฌ์ฉํ์ง ๋ง์์ผ ํ ๋ฉ์๋์ด๋ค.
๋ธ๋ก๊ทธ์ ์ ๋ณด
JiwonDev
JiwonDev