๐ ๋ฉ๋ชจ๋ฆฌ ๋์
์ปดํจํฐ ํ๋ก๊ทธ๋จ์ด ํ์ํ์ง ์์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณ์ ์ ์ ํ๊ณ ์๋ ํ์์ ๋งํ๋ค.
♦๏ธ ๊ฐ์ฒด๋ค์ ๋ค ์ด ์ฐธ์กฐ
๋ฐฐ์ด๋ก Stack ์ ๊ตฌํ
/** StackMemoryLeak.java */
public class StackMemoryLeak {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public StackMemoryLeak() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop() {
if (size == 0) {
throw new EmptyStackException();
}
Object result = elements[size - 1];
size--;
return result;
}
/**
* ์์๋ฅผ ์ํ ๊ณต๊ฐ์ ์ ์ด๋ ํ๋ ์ด์ ํ๋ณดํ๋ค.
* ๋ฐฐ์ด ํฌ๊ธฐ๋ฅผ ๋๋ ค์ผ ํ ๋๋ง๋ค ๋๋ต ๋ ๋ฐฐ์ฉ ๋๋ฆฐ๋ค. */
private void ensureCapacity() {
if (elements.length == size) {
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
}
์ด ์ฝ๋์์๋ ์คํ์ด ์ปค์ก๋ค๊ฐ ์ค์ด๋ค์์ ๋ ์คํ์์ ๊บผ๋ด์ง ๊ฐ์ฒด๋ค์ ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ํ์ํ์ง ์๋๋ค.
์ด ์คํ์ ์ฌ์ฉํ๋ ํ๋ก๊ทธ๋จ์ ์ค๋ ์คํํ๋ค ๋ณด๋ฉด ์ ์ฐจ ๋ฉ๋ชจ๋ฆฌ ๋์ ๊ฐ ์ผ์ด๋ ๊ฐ๋น์ง ์ปฌ๋ ์ ํ๋๊ณผ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ๋์ด๋ ๊ฒฐ๊ตญ ์ฑ๋ฅ์ด ์ ํ๋ ๊ฒ์ด๋ค.
์ฌํ ๊ฒฝ์ฐ ๋์คํฌ ํ์ด์ง*์ด๋ OutOfMemoryError๋ฅผ ์ผ์ผ์ผ ํ๋ก๊ทธ๋จ์ด ์๊ธฐ์น ์๊ฒ ์ข ๋ฃ๋ ์ ์๋ค.
์ Stack ์ฝ๋์์ elements ๋ฐฐ์ด์ ์ธ๋ฑ์ค๊ฐ size ์ด์์ธ ์์๋ค์ Stack์์ ๋นํ์ฑํ๋ ๊ฐ์ฒด์ง๋ง elements์ ๊ทธ๋๋ก ๋จ์ ๊ฐ์ฒด๋ค์ ๋ค ์ด ์ฐธ์กฐ(obsolete reference)๋ฅผ ์ฌ์ ํ ๊ฐ์ง๊ณ ์๋ค.
๋ฉ๋ชจ๋ฆฌ ๋์ ์ก๊ธฐ
๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ๋ณด๊ธฐ์๋ ๋นํ์ฑ ์์ญ์์ ์ฐธ์กฐํ๋ ๊ฐ์ฒด๋ ๋๊ฐ์ด ์ ํจํ ๊ฐ์ฒด์ด๊ธฐ ๋๋ฌธ์ ํด๋น ๊ฐ์ฒด๋ฅผ ๋ ์ด์ ์ฌ์ฉํ์ง ์์ ๊ฒ์ ํ๋ก๊ทธ๋๋จธ๊ฐ ์ง์ ์ฐธ์กฐ ํด์ ํ์ฌ ์๋ ค์ผ ํ๋ค.
/** StackMemoryLeak.java */
public Object pop() {
if (size == 0) {
throw new EmptyStackException();
}
Object result = elements[size - 1];
elements[size - 1] = null; // ํด๋น ์ฐธ์กฐ๋ฅผ ๋ค ์ผ์ผ๋ฏ๋ก null ์ฒ๋ฆฌ ํ์ฌ ์ฐธ์กฐ ํด์ ํจ
size--;
return result;
}
์์ฒ๋ผ ๊ฐ ์์์ ์ฐธ์กฐ๊ฐ ๋ ์ด์ ํ์ ์์ด์ง๋ ์์ . ์ฆ, ์คํ์์ ๊บผ๋ด์ง ๋ ์ฐธ์กฐ ํด์ ํ๋ค.
(์ฐธ๊ณ ) Stack
/** java.util.Stack.java */
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
removeElementAt(len - 1);
return obj;
}
/** java.util.Vector.java */
public synchronized void removeElementAt(int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
else if (index < 0) {
throw new ArrayIndexOutOfBoundsException(index);
}
int j = elementCount - index - 1;
if (j > 0) { // ์ค๊ฐ index ๊ฐ์ด ์ญ์ ๋ ๊ฒฝ์ฐ index ๋ค ๊ฐ๋ค์ ํ์นธ์ฉ ๋ก๊น
System.arraycopy(elementData, index + 1, elementData, index, j);
}
modCount++;
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
}
๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ null ์ฒ๋ฆฌ ํด์ผ ํ๋ ๊ฒฝ์ฐ
๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ null ์ฒ๋ฆฌํ๋ ์ผ์ ์์ธ์ ์ธ ๊ฒฝ์ฐ์ฌ์ผ ํ๋ค.
๋ค ์ด ์ฐธ์กฐ๋ฅผ ํด์ ํ๋ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ๊ทธ ์ฐธ์กฐ๋ฅผ ๋ด์ ๋ณ์๋ฅผ ์ ํจ ๋ฒ์ ๋ฐ์ผ๋ก ๋ฐ์ด๋ด๋ ๊ฒ์ด๋ค. ๋ณ์์ ๋ฒ์(scope)๋ฅผ ์ต์๊ฐ ๋๊ฒ ์ ์ํ๋ค๋ฉด ์ฐธ์กฐ๋ฅผ ์ง์ ํด์ ํด์ผ ํ ํ์๊ฐ ์์ด์ง๋ค.
♦๏ธ ์บ์
๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ์บ์์ ๋ฃ๊ณ ๋์, ์ด ์ฌ์ค์ ๊น๋งฃ๊ฒ ์์ ์ฑ ํ์ฐธ์ ๊ทธ๋ฅ ๋๋๋ ๊ฒฝ์ฐ๊ฐ ์๋ค.
์ฌ์ฉํ์ง ์๋ ์บ์์ ์ ์ฅ๋ ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ํด์งํ๊ธฐ ์ํ ํด๋ฒ์ ๊ฒฝ์ฐ์ ๋ฐ๋ผ ์ฌ๋ฌ๊ฐ์ง์ด๋ค.
(์ฐธ๊ณ ) ์๋ฐ์ ์ธ๊ฐ์ง ์ ํ์ ์ฐธ์กฐ*
WeakHashMap
์บ์ ์ธ๋ถ์์ ํค๋ฅผ ์ฐธ์กฐํ๋ ๋์๋ง ์ํธ๋ฆฌ๊ฐ ์ด์์๋ ์บ์๊ฐ ํ์ํ ์ํฉ์์ ์ฌ์ฉํ๋ฉด ์ ์ฉํ๋ค.
/** ReferenceTest.java */
public static void main(String[] args) {
HashMap<Integer, String> hashMap = new HashMap<>();
WeakHashMap<Integer, String> weakHashMap = new WeakHashMap<>();
Integer key1 = 1000;
Integer key2 = 2000;
Integer wKey1 = 1000;
Integer wKey2 = 2000;
hashMap.put(key1, "test a");
hashMap.put(key2, "test b");
weakHashMap.put(wKey1, "test a");
weakHashMap.put(wKey2, "test b");
key1 = null;
wKey1 = null;
System.gc(); //๊ฐ์ Garbage Collection
hashMap.entrySet().stream().forEach(el -> System.out.println(el));
System.out.println("--------");
weakHashMap.entrySet().stream().forEach(el -> System.out.println(el));
}
2000=test b
1000=test a
--------
2000=test b
- equals ๋ฉ์๋๊ฐ == ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ๋ Key๋ฅผ ์ด ๊ฒฝ์ฐ Key๊ฐ ๋ฒ๋ ค์ง๋ฉด ๋์ผํ Key๊ฐ ์์ฑ๋์ง ์๊ธฐ ๋๋ฌธ์ ๋ ์ ์ฉํ๋ค. (Key๊ฐ String๊ณผ ๊ฐ์ด ๋จ์ผ ๊ฐ์ ๊ฐ์ง๋ Class๊ณ == ์ฐ์ฐ์ ์ธ์ equals๋ฅผ ์ฌ์ฉํ์ฌ ์๋ก ๋ค๋ฅธ ๊ฐ์ฒด๋ผ๋ ๋์ผ์ฑ์ ์ฒดํฌํ์ฌ ์ ์งํ๊ณ ์ถ์ ๊ฒฝ์ฐ ์ ์ ํ์ง ์๋ค.)
- key๋ก ์ฐ๋ String์ ๋ฆฌํฐ๋ด ๋ฐฉ์์ผ๋ก ์์ฑํ ๊ฒฝ์ฐ String interning ๋๋ฌธ์ String pool์์ ๊ด๋ฆฌ๋๊ธฐ ๋๋ฌธ์ null์ด ๋๋ค๊ณ ํด๋ WeakHashMap์ด ์ญ์ ๋์ง ์๋๋ค.
- Value ๊ฐ์ฒด๊ฐ ์ง์ ๋๋ ๊ฐ์ ์ ์ผ๋ก ์์ ์ key๋ฅผ ๊ฐํ ์ฐธ์กฐ ํ์ง ์๋๋ก ์ฃผ์ํด์ผ ํ๋ค. ๋ง์ฝ key๋ฅผ ์ฐธ์กฐํ๋ value๋ฅผ ์ฌ์ฉํด์ผ ํ๊ณ , WeakHashMap๋ ์ฌ๋ฐ๋ฅด๊ฒ ๋์ํ๊ธธ ์ํ๋ค๋ฉด WeakReferences ๋ด์์ value๋ฅผ ๋ค์ ๋ํํ๋ ๋ฐฉ์์ ์จ์ผ ํ๋ค. ex) m.put(key, new WeakReference(value);
LinkedHashMap
์บ์ ์ํธ๋ฆฌ์ ์ ํจ ๊ธฐ๊ฐ์ ์ ํํ ์ ์ํ๊ธฐ ์ด๋ ต๊ธฐ ๋๋ฌธ์ ์๊ฐ์ด ์ง๋ ์๋ก ์ํธ๋ฆฌ์ ๊ฐ์น๋ฅผ ๋จ์ด๋จ๋ฆฌ๋ ๋ฐฉ์์ ํํ ํ์ฉํ๋๋ฐ, ์ด ๊ฒฝ์ฐ ์ฐ์ง ์๋ ์ํธ๋ฆฌ๋ฅผ ์ด๋ฐ๊ธ ์ฒญ์ํด์ค์ผ ํ๋ค.
removeEldestEntry ๋ฉ์๋๋ฅผ ์จ์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋๋ฅผ ํ์ฉํ๊ฑฐ๋ ์บ์์ ์ ์ํธ๋ฆฌ๋ฅผ ์ถ๊ฐํ ๋ ๋ถ์ ์์ ์ผ๋ก ์ํํ๊ฒ ํ๋ค.
♦๏ธ ๋ฆฌ์ค๋(listener) ํน์ ์ฝ๋ฐฑ(callback)
ํด๋ผ์ด์ธํธ๊ฐ ์ฝ๋ฐฑ์ ๋ฑ๋ก๋ง ํ๊ณ ๋ช ํํ ํด์งํ์ง ์๋๋ค๋ฉด ์ฝ๋ฐฑ์ ๊ณ์ ์์ธ๋ค.
์ฝ๋ฐฑ์ ์ฝํ ์ฐธ์กฐ(weak reference)๋ก ์ ์ฅํ๋ฉด ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ์ฆ์ ์๊ฑฐํ๋ค.
ex) WeakHashMap์ ํค๋ก ์ ์ฅํ๊ธฐ
*ํ์ด์ง : ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ์์ ์ฌ์ฉ๋์ง ์๊ณ ์๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ด ํ๋ ๋๋ผ์ด๋ธ์ ์ผ์์ ์ผ๋ก ์ ์ฅ๋๋ ๊ฒ
*์๋ฐ์ ์ธ ๊ฐ์ง ์ ํ์ ์ฐธ์กฐ
- ๊ฐํ ์ฐธ์กฐ(Strong reference)
Integer strong = 1;
๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ์ฐธ์กฐ ์ ํ
num ๋ณ์๋ ๊ฐ์ด 1์ธ Integer ๊ฐ์ฒด์ ๋ํด ๊ฐํ ์ฐธ์กฐ๋ฅผ ๊ฐ์ง๋ค.
๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋ ๊ฐํ ์ฐธ์กฐ๊ฐ ์๋ ๊ฒฝ์ฐ ๊ทธ ๊ฐ์ฒด๋ ๊ฐ๋น์ง ์ปฌ๋ ์ ์ ๋์์ด ๋์ง ์๋๋ค.
- ๋ถ๋๋ฌ์ด ์ฐธ์กฐ(Soft reference)
SoftReference<Integer> soft = new SoftReference<Integer>(strong);
๋ง์ฝ strong == null์ด ๋๋ฉด ๋ ์ด์ ์๋ณธ(storng)์ด ์กด์ฌํ์ง ์์ผ๋ฏ๋ก soft ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ๊ฐ์ฒด๊ฐ SoftReference๋ง ์กด์ฌํ ๊ฒฝ์ฐ ๊ฐ๋น์ง ์ปฌ๋ ์ ๋์์ด ๋๋ค.
๋จ, ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ถ์กฑํ์ง ์์ผ๋ฉด ๊ตณ์ด ๊ฐ๋น์ง ์ปฌ๋ ์ ํ์ง ์๋๋ค.
์๊ฒฉํ์ง ์์ ์บ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ค์์ ์ฌ์ฉ๋๋ค.
- ์ฝํ ์ฐธ์กฐ(Weak reference)
WeakReference<Integer> weak = new WeakReference<Integer>(strong);
๋ง์ฝ strong == null์ด ๋๊ณ weak ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋ ์ฐธ์กฐ๊ฐ WeakReference ๋ฟ์ผ ๊ฒฝ์ฐ ๊ฐ๋น์ง ์ปฌ๋ ์ ๋์์ด ๋๋ค.
๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ถ์กฑํ์ง ์๋๋ผ๋ ๊ฐ๋น์ง ์ปฌ๋ ์ ์ ๋์์ด ๋์ด ๋ค์ ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ๋์ํ๋ ์์ ์ ๋ฌด์กฐ๊ฑด ์์ด์ง๋ค.
์ฐธ๊ณ ํ ๊ณณ ์ถ์ฒ
https://blog.breakingthat.com/2018/08/26/java-collection-map-weakhashmap/
'reviews > Effective JAVA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
010. equals๋ ์ผ๋ฐ ๊ท์ฝ์ ์ง์ผ ์ฌ์ ์ํ๋ผ (0) | 2022.04.07 |
---|---|
009. try-finally๋ณด๋ค๋ try-with-resource๋ฅผ ์ฌ์ฉํ๋ผ (0) | 2022.03.19 |
006. ๋ถํ์ํ ๊ฐ์ฒด ์์ฑ์ ํผํด๋ผ (0) | 2022.03.04 |
005. ์์์ ์ง์ ๋ช ์ํ์ง ๋ง๊ณ ์์กด ๊ฐ์ฒด ์ฃผ์ ์ ์ฌ์ฉํ๋ผ (0) | 2022.02.25 |
004. ์ธ์คํด์คํ๋ฅผ ๋ง์ผ๋ ค๊ฑฐ๋ private ์์ฑ์๋ฅผ ์ฌ์ฉํ๋ผ (0) | 2022.02.25 |