글
[Java] non-static inner class 는 메모리 릭을 발생시키는가?
아니다. 단지 GC의 성능을 나쁘게 만들 뿐이다.
아래의 예를 보자.
Main.java
public class Main {
Outer outer;
void alloc() { outer = new Outer(); }
void free() { outer = null; }
}
Outer.java
public class Outer {
Inner inner = new Inner();
public class Inner {
}
}
non-static inner 클래스는 outer 클래스에 대한 암묵적인 레퍼렌스를 가진다.
Main 클래스의 alloc() 메소드와 free() 메소드를 차례대로 실행시키면
객체들은 아래와 같은 레퍼런스를 가지게 될 것이다.
먼 옛날(?) Inner Class가 처음 소개되던 JDK 1.1 시절에 쓰여진 글들을 보면
메모리 릭을 발생시킬 수 있다는 글들이 있다.
outer와 inner가 서로의 레퍼런스를 가지고 있어 레퍼런스 카운트가 0이 되지 않아
GC가 메모리를 해제할 수 없다는 생각이 었던 것 같다.
(JDK 1.1 초기에는 실제로 그렇게 동작했을지도 모르지만,
JDK 1.1을 설치해서 확인하고 싶은 생각까지는 없는 관계로... Pass)
하지만 Garbage Collector는 Unreachable object에 대해서 메모리를 해제한다.
메모리가 할당된 object들의 연관 관계를 그래프로 표현한다고 생각해보자.
레퍼런스 카운트가 0인 object는 쉽게 찾을 수 있지만,
레퍼런스 카운트가 0보다 큰 object인 경우는,
그래프의 시작 노드에서 모든 노드를 방문했을 때 방문하지 않은 노드를 찾아서
메모리를 해제해야 하기 때문에 Grabage Collector의 성능이 떨어질 수 밖에 없다.
이것을 보여주는 적절한 예제를 작성하려 했는데 시간 관계상 패스.
위 링크를 참고해 보시라.
결론:
inner 클래스를 가지는 객체가 빈번하게 만들어지도 버려진다면, (만들어진 객체에
대한 레퍼런스를 유지하지 않는다는 의미. 로컬 메소드에서만 사용되는 것 처럼)
non-static static으로 inner 클래스를 구현하는 것이 어플리케이션 성능을 좋게 만들 것이다.
추가로 outer 클래스에 대한 암묵적인 레퍼런스를 없앨 수 있으므로 메모리 절약에도
약간 도움을 줄 수 있을 것이다. (물론 실제로는 아닐 가능성이 더 클것 같다.
WeakReference를 사용해야 할 경우가 있을 수도 있고, outer 클래스에 직접 접근이
불가능 하므로 필요한 멤버 변수를 추가로 가지고 있어야 할 수도 있다)
다음 글은 이 글을 쓰게 된 동기인 Android의 lint 이슈인 HandlerLeak에 대해서 알아보겠다.
'프로그래밍' 카테고리의 다른 글
[안드로이드] 데이터 바인딩 라이브러리 (1) | 2018.01.23 |
---|---|
PKI 의 기본 개념 설명 (0) | 2017.03.23 |
Mockito, PowerMock, Roboletric 어떤 것을 선택할 것인가? (2) | 2016.10.25 |
전체 프로젝트에서 한 번만 사용하는 스트링도 Constant로 사용해야 할까? (0) | 2016.06.23 |
Technical Debt (기술적 빚 / 기술부채) (0) | 2016.05.19 |