对本地变量

时间:2018-04-13 19:47:29

标签: java android java-memory-leaks

我在Android应用中遇到了报告内存泄漏,经过一些调查我几乎找到了泄漏的位置,这里是简化代码:

public class LeakTracker {
    public static List<Callback> callbacks = new ArrayList<>();
    public static List<WeakReference<LeakingActivity>> weakList = new ArrayList<>();

    // causes leak of activity
    public void startLeak(final LeakingActivity activity) {
        callbacks.add(new Callback() {
            // remove this line then no leak
            Wrapper wrapper = new Wrapper(activity);
            @Override
            public void onCall() {
            }
        });
    }

    // no leak here
    public void startLeak2(final LeakingActivity activity) {
        weakList.add(new WeakReference<>(activity));
    }

    public interface Callback {
        void onCall();
    }

    static class Wrapper {
        private WeakReference<LeakingActivity> weakReference;

        public Wrapper(final LeakingActivity activity) {
            weakReference = new WeakReference<LeakingActivity>(activity);
        }
    }
}

泄漏的发生是因为我调用了一个函数&#34; startLeak&#34;。活动变量将被泄露。但是,如果我打电话给&#34; startLeak2&#34;泄漏不会发生。我想知道为什么第一种情况会发生泄漏。 Wrapper也使用WeakReference。

LeakActivity类占用大约30M的内存。在Android设备上调用startLeak大约5次会导致OOM。打电话给startLeak2赢了。如果使用startLeak而不是startLeak2,LeakCanary工具会报告泄漏。

1 个答案:

答案 0 :(得分:1)

在第一种方法中,您已宣布活动为最终。这会将活动的引用添加到Callback实例,因此不是Wrapper泄漏,而是Callback本身。

另外,请记住Callback是一个匿名内部类,它还将包含对外部类LeakTracker的引用