Android memory leak with static final

谁说胖子不能爱 提交于 2021-02-07 03:49:34

问题


The question is on using static final constants which apparently causes memory leaks: I have been searching for information on how not to cause memory leaks in Android Apps. One big problem is using private static final for constants. Apparently that is how constants should be defined. But static final means it hangs around after a rotation and means the Activity cannot be cleared.

Obviously I am misunderstanding something. I know that putting variables in the Application context allows them to hang around without causing problems.

As a general question on memory leaks: There are lots of information on memory leaks, but I cannot find anything that sums up all the information clearly. Any recommendations where it is all fully explained.


回答1:


This information is incorrect. Making a variable static final will not cause any kind of memory leaks just because it was marked static final. That is not to say you can't create memory leaks by doing that though. One thing you want to make sure to avoid is creating a static variable that is of type context (such as activity). When you create a static reference to a context you are possibly creating a memory leak. A static variable means there is only one copy of that variable for your entire application and across instances of that class. It also means that it will remain in memory until it is explicitly cleared or the application is shutdown. Static variables are class level variables and are not attached to any specific instance of an object. When you create for example a 'public static final string myString = "Hello"' you will never be causing a memory leak. This way of define a constant will actually save memory vs using 'public final string myString = "Hello"' because without static a memory location will be created to store that string for every instance of this class instead of just having one copy for all instances to use.




回答2:


in Java, Static variables live on the heap, and are allocated when their class loads. Instance variables' garbage collection eligibility is tied to their instance.

Using value-type(int, bool, double, etc.) static variables will not leak instances of the class. When you allow non-value-type static variables, you can leak anything referenced by these static variables.

Consider a simple class

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;
    }
}

if you keep references to Activity objects (even if the reference type is Context) in static variables, you'll leak the Activity object.

Keep in mind that Android doesn't run on a real JVM, but on the Dalvik VM, so your results may vary in theory, but I'd be very surprised to find that Dalvik differs as far as GC eligibility is concerned (I haven't run into any issues myself).

Edit - Looking again at the question, I think this may clear up some understanding: An object won't become eligible for garbage collection as long as it can be reached by following reference chains from GC roots. Activity objects are instantiated and kept alive normally by the Android process (which i assume is kept alive with something at least analagous to static void main(string[] args).

Once the system calls yourActivityInstance.onDestroy() and releases the refefence, that object is eligible to be GCed (and subsequently, all objects it references), UNLESS the instance of your activity is reachable from a GC root through another reference. If this reference is held longer than it should be held (read: indefinitely), you've leaked this object, since GC can't be sure that it can safely free the leaked object's resources.

It doesn't matter how this reference is held (static or non-static, final or non-final). As long as an object can be reached from a GC root (at least local and in-scope variables in static methods, static fields in loaded classes), you're going to leak.




回答3:


This is a pretty good video that addresses all of Android memory management, and goes into detail about detecting memory leaks. Not quite what your asking for, but its worth mentioning in the same thread.

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




回答4:


Static constants do not necessarily hold activities around and are very standard. The issue comes with when you have a static which holds a reference to your activity (such as views or drawables) which live beyond the intended life of that activity.

Decent starting points for memory analysis here, here, and here. You would also be well served just investigating how garbage collection works in general.




回答5:


Constants do not cause memory leaks if you are not referencing the Activity itself. There is no problem with using (e.g. String) constants in your Activity.

There are two good resources capturing that topic about memory leaks:

  • Description from Android Developer Blog here
  • The Google IO presentation about Memory Management here


来源:https://stackoverflow.com/questions/10018193/android-memory-leak-with-static-final

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!