※ 내부 클래스/정적 내부 클래스 스레드에서 GC(가비지 컬렉션)
- 내부 클래스 스레드에서 GC
: 내부 클래스는 외부 클래스의 멤버에 접근할 수 있다. 즉, 내부 클래스는 암시적으로 외부 클래스에 대한 참조를 가진다. 따라서 내부 클래스로 정의된 스레드는 스레드가 실행되는 동안 외부 클래스에 대한 참조를 유지하기 때문에 외부 클래스의 모든 객체는 스레드가 실행되는 한 내부 클래스와 함께 메모리에 있어야 한다. 익명 내부 클래스도 마찬가지다.
public class Outer{ public void sampleMethod(){ SampleThread sampleThread = new SampleThread(); sampleThread.start(); } private class SampleThread extends Thread{ public void run(){ ..... } } }
- 정적 내부 클래스 스레드에서 GC
: 정적 내부 클래스는 외부 클래스의 정적 멤버가 아닌 멤버에 접근 못 한다. 외부 클래스 인스턴스 멤버이기 때문이다. 따라서 정적 내부 클래스로 정의된 스레드는 외부 객체 자체가 아닌 외부 객체 클래스(Outer.class)에 대한 참조만 유지한다. 즉, 외부 객체는 자신을 참조하는 다른 객체가 사라지면 가비지 컬렉션될 수 있다.
public class Outer{ public void sampleMethod(){ SampleThread sampleThread = new SampleThread(); sampleThread.start(); } private static class SampleThread extends Thread{ public void run(){ .... } } }
단 예외가 있다. 스레드를 생성할 때 Runnable 객체를 외부 클래스의 내부 클래스로 생성하면 Runnable객체가 외부 클래스에 대한 참조를 유지하게 된다. 이 때는 해당 스레드가 끝날 때 까지 외부 클래스 객체는 가비지 컬렉션이 되지 않는다. 다음은 그 예이다.
public class Outer{ public void sampleMethod(){ SampleThread sampleThread = new SampleThread(new Runnable() { @Override public void run() { ... } }) } private static class SampleThread extends Thread{ public SampleThread(Runnable runnable){ super(runnable); } } }
이런 메모리 누수를 방지하는 방법으로는 정적 내부 클래스를 사용, 약한 참조 사용, 메시지 큐 정리 등이 있다. 이에 대해서는 "안드로이드 기본적인 메모리 누수 방지" 포스트에서 확인 바란다.
'안드로이드 > 비동기, 멀티스레드' 카테고리의 다른 글
안드로이드 스레드에서 기본적인 메모리 누수 방지 (0) | 2017.08.12 |
---|---|
안드로이드 핸들러(Handler)에서 메모리 누수, GC (0) | 2017.08.11 |
안드로이드 서비스 총정리(스타티드/바운드 서비스) (0) | 2017.08.04 |
안드로이드 백그라운드 스레드(HandlerThread, 스레드 풀 - Executor, AsyncTask) (0) | 2017.08.01 |
메인 스레드와 Handler, Looper 내부 구조 이해와 활용 (0) | 2017.07.31 |