Rx의 도입과 액티비티를 옵저버로 관리하게 되니, 메모리 누수라는 골치아픈게 발생하고 있습니다.


WeakReference 클래스를 사용하면 된다고 나오지만, 정확히 이해가 가지 않아, 테스트 코드를 작성해보았습니다.


일단, WeakReference 를 사용하지 않을 경우.

- 확인해보면 GC 가 강제 실행되었지만, A 내부 B 객체가 살아있음을 알 수 있습니다. (컬렉션이 물고 있기 때문이죠.)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class Test {
 
    public static class A {
        private B b = new B();
 
        public B getB() {
            return b;
        }
 
        public void setB(B b) {
            this.b = b;
        }
 
        public static final class B {
            public String text = "아직 살아있다.";
        }
    }
 
    public static void main(String[] args) {
        // TODO Auto-generated method stu
        A a = new A();
        HashSet<A.B> abc = new HashSet<>();
 
        abc.add(a.getB());
        a = null;
        System.gc(); // GC 강제 발생
 
        for (A.B b : abc) {
            System.out.println(b.text);
        }
    }
}
 
// 아직 살아있다.
 
cs


WeakReference 로 참조를 유지할 경우.

- GC 가 돌며, A 의 인스턴스가 삭제되었고, 참조하고 있던 B의 인스턴스도 삭제가 되었음을 알 수 있습니다. (안드로이드에서도 이 힌트를 가지고, 메모리 릭을 방지할 수 있을 것이라 생각합니다. ㅡㅡ^)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class Test {
 
    public static class A {
        private B b = new B();
 
        public B getB() {
            return b;
        }
 
        public void setB(B b) {
            this.b = b;
        }
 
        public static final class B {
            public String text = "아직 살아있다.";
        }
    }
 
    public static void main(String[] args) {
        // TODO Auto-generated method stu
        A a = new A();
        HashSet<WeakReference<A.B>> abc = new HashSet<>();
 
        abc.add(new WeakReference<>(a.getB()));
 
        a = null;
        System.gc();
 
        for (WeakReference<A.B> b : abc) {
            System.out.println(b.get().text);
        }
    }
}
 
// Exception in thread "main" java.lang.NullPointerException
    at Test.main(Test.java:31)
 

cs


반응형
Posted by N'