4

问题在于使用显然会导致内存泄漏的静态最终常量:我一直在寻找有关如何在 Android 应用程序中不导致内存泄漏的信息。一个大问题是使用 private static final 作为常量。显然这就是应该如何定义常量。但是静态最终意味着它在旋转后挂起并且意味着无法清除 Activity。

显然我误解了一些东西。我知道将变量放在应用程序上下文中可以让它们在不引起问题的情况下徘徊。

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

4

5 回答 5

12

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

于 2012-04-04T19:51:47.793 回答
5

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

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

考虑一个简单的类

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 根的引用链来访问对象,它就不会成为垃圾收集的条件。Activity 对象由 Android 进程实例化并正常保持活动状态(我假设它保持活动状态至少类似于static void main(string[] args).

一旦系统调用 yourActivityInstance.onDestroy() 并释放引用,该对象就有资格被 GC(以及随后它引用的所有对象),除非您的活动实例可以通过另一个引用从 GC 根访问。如果这个引用的持有时间超过了它应该持有的时间(阅读:无限期地),你已经泄漏了这个对象,因为 GC 不能确定它可以安全地释放泄漏对象的资源。

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

于 2012-04-04T21:05:33.467 回答
2

这是一个很好的视频,它解决了所有的 Android 内存管理问题,并详细介绍了检测内存泄漏。不完全符合您的要求,但值得在同一个线程中提及。

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

于 2012-04-04T19:59:17.937 回答
0

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

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

  • Android 开发者博客的描述在这里
  • 关于内存管理的 Google IO 演示在这里
于 2012-04-04T19:55:50.113 回答
0

静态常量不一定保持周围的活动并且非常标准。当您有一个静态引用您的活动(例如视图或可绘制对象),该引用超出该活动的预期寿命时,就会出现问题。

这里这里这里是内存分析的不错起点。只需调查垃圾收集的一般工作原理,您也会得到很好的服务。

于 2012-04-04T19:56:06.487 回答