Android内存泄漏与静态最终

时间:2012-04-04 19:45:37

标签: android memory-leaks static

问题是使用静态最终常量显然会导致内存泄漏:我一直在搜索有关如何在Android应用中导致内存泄漏的信息。一个大问题是对常量使用private static final。显然,应该如何定义常量。但静态最终意味着它在旋转后会挂起并意味着无法清除活动。

显然我误解了一些事情。我知道将变量放在Application上下文中允许它们在不引起问题的情况下挂起。

作为关于内存泄漏的一般性问题:有很多关于内存泄漏的信息,但我找不到任何能够清楚地总结所有信息的内容。任何完全解释的建议。

5 个答案:

答案 0 :(得分:12)

此信息不正确。使变量静态final不会因为标记为static final而导致任何类型的内存泄漏。这并不是说你不能通过这样做来创建内存泄漏。您要确保避免的一件事是创建一个类型为context的静态变量(例如activity)。当您创建对上下文的静态引用时,您可能会创建内存泄漏。静态变量意味着整个应用程序和该类的实例只有该变量的一个副本。它还意味着它将保留在内存中,直到它被明确清除或应用程序关闭。静态变量是类级变量,不附加到对象的任何特定实例。例如,当您创建'public static final string myString =“Hello”'时,您将永远不会导致内存泄漏。这种定义常量的方式实际上会节省内存与使用'public final string myString =“Hello”',因为如果没有静态,将创建一个内存位置来为该类的每个实例存储该字符串,而不是只为所有实例提供一个副本使用。

答案 1 :(得分:5)

在Java中,静态变量存在于堆上,并在其类加载时分配。实例变量的垃圾收集资格与其实例相关联。

使用value-type(int,bool,double等)静态变量不会泄漏类的实例。当您允许非值类型的静态变量时,您可以泄漏这些静态变量引用的任何内容。

考虑一个简单的类

public class Activity extends Context {
    static int willNotLeakActivity = 0;
    static Context mayLeakActivity = new Context();

    //if you call activityA.leakyMethod(activityA); you will leak activityA
    public void leakyMethod(Context context){
        mayLeakActivity = context;
    }

    //this method won't leak the instance
    public void safeMethod(int arg){
        willNotLeakActivity = arg;
    }
}

如果在静态变量中保留对Activity对象的引用(即使引用类型为Context),则会泄漏Activity对象。

请记住,Android不是在真正的JVM上运行,而是在Dalvik VM上运行,因此您的结果可能在理论上有所不同,但我发现Dalvik与GC资格有所不同,我会感到非常惊讶(我自己没有遇到任何问题)。

编辑 - 再看一下这个问题,我认为这可能会让人理解: 只要可以通过GC根目录中的以下引用链来访问对象,就不会有资格进行垃圾回收。活动对象通过Android进程实例化并保持活动状态(我假设它至少与static void main(string[] args)类似的东西保持活着。

一旦系统调用yourActivityInstance.onDestroy()并释放refefence,该对象就有资格被GCed(随后是它引用的所有对象),除非您的活动实例可以通过另一个引用从GC根目录到达。如果此引用的持续时间超过应该保持的时间(读取:无限期),则表示您已泄漏此对象,因为GC无法确定它是否可以安全地释放泄漏对象的资源。

此引用的保持方式无关紧要(静态或非静态,最终或非最终)。只要可以从GC根目录(至少是静态方法中的本地和范围内变量,加载类中的静态字段)到达对象,您就会泄漏。

答案 2 :(得分:1)

这是一个非常好的视频,可以解决所有Android内存管理问题,并详细介绍了如何检测内存泄漏。不是你要求的,但它在同一个帖子中值得一提。

http://www.youtube.com/watch?v=_CruQY55HOk

答案 3 :(得分:0)

如果您没有引用Activity本身,则常量不会导致内存泄漏。在Activity中使用(例如字符串)常量没有问题。

有两个很好的资源可以捕获有关内存泄漏的主题:

  • Android开发者博客here
  • 的说明
  • 关于内存管理的Google IO演示here

答案 4 :(得分:0)

静态常量不一定包含活动,非常标准。当您拥有一个静态时,会出现问题,该静态包含对您的活动的引用(例如视图或绘图),这些活动超出了该活动的预期寿命。

内存分析的最佳起点hereherehere。您也可以很好地调查垃圾收集的工作原理。