了解Android应用程序中的内存泄漏

时间:2015-05-14 19:36:56

标签: java android memory-leaks

我对Java编程很陌生,有很多C ++经验,而且我正在阅读有关引用如何导致Android应用程序内存泄漏的内容。 This explanation让我难过。在“第二课”中,它说:

  

关键是,当Activity的实例结束时,Activity不知道SomeObject的生命周期将结束。如果该对象保留在内存中,它将在内存中保存该活动[...]。

正如我所看到的那样(可能错误;请纠正我),当活动结束时,SomeObject被销毁(假设没有其他参考存在)。活动引用SomeObject,而不是相反。我不明白为什么在这里泄露任何东西,更不用说整个活动了。

3 个答案:

答案 0 :(得分:2)

这与他们为EventListener创建一个匿名类的事实有关。

public void onResume() {
    super.onResume();

    SomeObject object = new SomeObject();

    object.setSuccessListener(new EventListener<Boolean>() {
        public void onEvent(Boolean response) {
            Log.d(TAG_NAME, "Valid response? "+response);
        }
    });

    SomeObjectManager.getSingleton().addObject(object);
}
  • 明确指出,这是在活动中完成的 的onResume()。

  • 匿名类(以及非静态内部类)具有对其周围类的隐式引用。所以在这种情况下,EventListener引用了Activity本身。

  • 因此,SomeObject具有对Activity的引用,因为它引用了实现EventListener的Anonymous类。

以下是您在问题中引用的引用之前的文字:

  

例如,在上面的示例中:我们附加了对我们的引用   某个对象的活动实例,可能是持久的,并且在一个   经理某处。重点是......

因此SomeObjectManager类在活动被销毁时不会消失,它保存对SomeObject的引用,SomeObject保存对EventListener的引用,EventListener又引用Activity。

所以当你说:

  

正如我所看到的那样(可能是错误的;请纠正我),当活动时   结束,SomeObject被销毁(假设没有其他引用它   存在)。该活动引用SomeObject,而不是反过来。

该逻辑中的缺陷是SomeObject DOES通过EventListener引用该活动。

这有帮助吗?

答案 1 :(得分:2)

以下是答案:How Does this Escape?

如果你能这样做,那么在调试器中运行它并设置断点:

Log.d(TAG_NAME, "Valid response? "+response);

现在查看'this'实例有哪些成员。特别是您对this$0感兴趣。

所以电话很重要:

objectFromBefore.setSuccessListener(null);

看看之前会发生什么:

object.setSuccessListener(new EventListener<Boolean>() {
    public void onEvent(Boolean response) {
        Log.d(TAG_NAME, "Valid response? "+response);
    }
});

SomeObjectManager.getSingleton().addObject(object);

现在链是:

SomeObjectManager - &gt;单身 - &gt; listofObjects - &gt;对象

和对象:

object-&gt; successListeners-&gt; anonymous EventListener-&gt; this $

这个$这是你的外部实例,即活动。

答案 2 :(得分:2)

不幸的是,泄漏活动非常容易。我所知道的一些Android开发者很高兴(有时是故意的)忘记了这个事实。感谢你的关心,知道你想了解更多,以避免这种情况。

泄露活动的一些常见方法

1)设置/添加/注册您的Activity作为监听器或观察者,忘记设置(null)/删除/取消注册活动。

2)将对Activity的引用移交给使用静态引用而不清除静态引用的任何内容。 (单身就是一个例子)

3)使用非静态内部类。 (匿名内部类处理程序就是一个例子)

您可以采取一些措施来避免这些类型的泄漏

1)记得设置(null)/删除/取消注册你的活动

2)作为软件设计的一部分,请将处理Activity的组件烘焙到Activity生命周期的概念中。

3)使内部类静态,并且需要引用外部类的地方,使用WeakReferences

4)尽可能使用应用程序上下文而不是Activity上下文。

您的活动将被销毁和重新创建的一些常见情况

1)如果您在应用中允许更改方向,则从纵向切换到横向时,活动将被销毁并重新创建,反之亦然。

2)使用设备的后退按钮退出应用程序将导致当前活动被销毁(即使应用程序本身仍将继续运行。)

3)虽然更为罕见,但Android可以随意终止您的Activity以释放资源并使设备对用户保持响应。

您应该熟悉Android Studio的设备监视器,hprof-conv工具和Eclipse Memory Analyzer工具。我发现测试我的应用程序以查看它是否正在泄漏活动的最简单方法是在我进入应用程序时使用设备监视器中的内存配置文件,使用设备后退按钮退出它,然后返回到应用程序通过单击应用程序托盘中的图标或转到最近。重复几次,然后创建一个内存转储文件。在此转储文件上运行hprof-conv工具,将其转换为MAT可以理解的格式,然后在MAT中打开它。

有很多关于获取内存配置文件和使用MAT的教程。只需进行网络搜索。