Map 을 자주 사용하는 편인데, WeakHashMap 이 그냥 많이들 쓰는 듯 해서 아무데나 마구잡이로 쓰고 있었는데, 문제가 발생했다. ^^;;;
갑자기 Map 의 key 가 사라졌다. API 문서(ref. 1) 를 보면 그런 경우에 대한 경고를 하고 있었다. 여하튼 그래서 조금 더 정리를 했다.
WeakHashMap
이녀석의 key 는 더이상 쓸모가 없다고 JVM 등이 판단을 하면, 자기 마음대로 garbage collector(GC) 에게 넘겨버리고 null 을 return 한다. 물론 이때 알아서 key 와 value 의 값의 메모리를 정리한다.[ref. 1]판단의 기준은 reference 가 얼마나 되고 있느냐로 판단한다.[ref. 2] 근데 weak reference 만 가지고 있다면 이 녀석은 GC 가 마음대로 없애버릴 수 있다.
그래서 쉽게 얘기하면, 이녀석으로 만들어 놓은 Map 의 size 가 바뀔 가능성이 다분하다.
그렇기 때문에 절대 사라져서는 안될 녀석에 대한 Map 을 만들 생각이라면 이녀석을 사용하면 안된다.
그런데 이녀석을 왜 만들어 놨을까?
그것에 대한 대답은 ref. 2 에서 해 준다. garbage collecting 을 잘 해서 메모리 누수(Memory leak) 이 안되게 해주는 장점을 가진다.
지금 이녀석을 사용하고 있는데, 대부분의 경우에서는 크게 문제를 보이지 않는다.
특히 Cache 를 위한 map 을 만들때는 충분하다. 왜냐하면 어차피 cache 는 일정 용량(capacity) 이상에서는 없애야 하는 녀석들이니, null 을 return 하면 다시 data 를 가져오면 된다.
그런데 static 한 녀석으로 사용하려고 한다면, weak reference 를 사용하는 WeakHashMap 은 어울리지 않는다. 왜냐하면, weak reference 만 가지고 있는 상태에서는 언제 GC 가 없애버릴 수 알 수 없기 때문이다.
그러므로 이럴 때는 그냥 일반적인 HashMap 등을 사용하는 것이 훨씬 나은 선택일 수 있다.
예제
아래에서 WeakHashMap 을 사용했다. 그런데 한번의 access 후에 key 가 사라져 버렸다. 아마 reference 가 처음 put() 할 때 +1 되고는 get() 하면서 -1 이 되는 듯 하다.여하튼 그래서 아래 경우에는 쓸 수 없었다.
public class ItemAdapter extends BaseAdapter{ private WeakHashMap<String, String> mStateMap; ... public synchronized void init(Activity c){ ... mFilesStateMap.put(filename, STATE_PLAY); } @Override public View getView(int position, View convertView, ViewGroup parent) { ... holder.calendarBottom.setText(mFilesStateMap.get(item.getFileName())); ... } }
하지만 local 에서 new 를 해서 local 에서만 사용하는 경우에는 괜찮은 듯 하다. 어차피 local 에서는 많이 쓸 일도 없고, 중간에 GC 를 부를 일도 많지 않은 듯 하기 때문이다. (물론 위험의 가능성은 언제나 열려 있다. ^^;;)
댓글 없음:
댓글 쓰기