问题是使用静态最终常量显然会导致内存泄漏:我一直在搜索有关如何在Android应用中导致内存泄漏的信息。一个大问题是对常量使用private static final。显然,应该如何定义常量。但静态最终意味着它在旋转后会挂起并意味着无法清除活动。
显然我误解了一些事情。我知道将变量放在Application上下文中允许它们在不引起问题的情况下挂起。
作为关于内存泄漏的一般性问题:有很多关于内存泄漏的信息,但我找不到任何能够清楚地总结所有信息的内容。任何完全解释的建议。
答案 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内存管理问题,并详细介绍了如何检测内存泄漏。不是你要求的,但它在同一个帖子中值得一提。
答案 3 :(得分:0)
如果您没有引用Activity本身,则常量不会导致内存泄漏。在Activity中使用(例如字符串)常量没有问题。
有两个很好的资源可以捕获有关内存泄漏的主题:
答案 4 :(得分:0)