[Android] Android Memory Leak 사례

백중원 (Leopold)
4 min readDec 22, 2016

--

막아야 하느니라..

Android를 개발하다 보면 무의식중에 Memory Leak을 유발하는 코드를 작성하게 될 가능성이 있다.

보통 가장 쉽게 Memory Leak을 유발하는 경우는 Activity나 Android에 종속되는 컴포넌트들을 static 리소스로 관리하게 되는 경우이다. 하지만 실제로 이렇게 코딩하는 개발자는 거의 없으리라 생각된다.

그 외에 Memory Leak을 유발할 수 있는 케이스는 Inner ClassAnonymous Class 등을 사용하면서 발생할 수 있다. Inner Class, Anonymous Class 등에 관련된 실제 코드상에서 관련될만한 클래스들은 Handler, AsyncTask, Thread, Timer 등이 있다.

실제 Memory Leak을 유발하는 코드를 작성하기 전에 GC 동작에 대해서 이해가 필요하다. GC 알고리즘에 대해서는 별도로 포스팅을 해야 될 만큼 방대하기 때문에 여기서는 간략히 설명하겠다.

기본적으로 Java의 일반적인 객체는 strong reference이다. 보통 GC 대상을 선정하는 과정에서 reachable, unreachable로 나뉘게 되는데 root set으로부터 시작된 참조 사슬에 포함되어 있으면 reachable 객체, 참조 사슬에서 자신을 참조하고 있는 reachable 객체가 없을 경우 unreachable 객체로 나뉘게 된다.

물론 WeakReference, SoftReference, PhantomReference 등을 적용하면 GC 과정에서 사용자의 개입이 일어날 수 있지만 이 글에선 논외로 하겠다.

간단히 풀어서 이야기하면 자신을 참조하고 있는 객체가 있을 경우 GC 대상이 되지 않는다는 것이다.

아래는 대표적인 Android에서의 Handler의 Memory Leak을 유발하는 코드이다.

위 코드는 onCreate에서 handler로 1분 뒤에 어떤 작업을 하도록 요청을 하고 그 아래에선 Activity를 종료하도록 finish() 메서드를 수행한다. Java에서 non-static inner class의 경우 outer class에 대한 reference를 가지게 된다. 위 코드에서 non-static inner class로 선언된 HandlerLeakActivity에 대한 reference를 가지고 main thread에서 생성하였기 때문에 main thread의 Looper 및 Message Queue에 바인딩 된다.

LeakActivity가 종료가 되었지만 Message Queue에 delay된 작업이 남아 있고 handler에서는 LeakActivity에 대한 reference가 남아 있기 때문에 LeakActivity는 GC의 대상이 되지 않는다.

아마 Android Studio에서 위와 같은 코드를 작성하면 Lint 메시지가 뜰 것이다.

그렇다면 어떻게 해야 Memory Leak이 발생하지 않을까? non-static inner classouter class에 대한 reference를 가지지만 static inner classouter class에 대한 reference를 가지지 않는다. 그리고 추가로 Handler 내부에서 Activity의 메서드나 변수 등 리소스를 참조해야 될 경우 WeakReference를 활용해야 한다.

위 코드를 보면 RunnableAnonymous class에서 static inner class로 변경한 것도 눈여겨봐야 된다. Anonymous classnon-static inner class와 동일하게 outer class에 대한 reference를 가지게 된다.

결론은 Inner Class 의 경우 Activity의 Lifecycle에 동일하게 생성 및 종료가 보장된다면 non-static inner class로 정의해도 되지만 그렇지 않은 경우 static inner class로 정의해야 된다는 것이다.

--

--

백중원 (Leopold)

스타트업에서 ‘트리플’ 이라는 여행 서비스를 개발하고 있습니다. 디지털 노마드와 조기 은퇴를 꿈꾸는 평범한 개발자입니다.