Android leaking memory in View.setTag()

Activity (and associated views) Leaks

Found that the implementation of View.setTag(int, object) has bug that may possibly cause memory leak. Did a quick search in Google and found that I am not alone. This guy noticed that the problem is because of

private static WeakHashMap<View, SparseArray> sTags;

Update: Download test project file.

and whenever a View has a tag referenced the View it will cause the memory leak. I did a quick test with following two versions (both sitting in the onCreate() of activity:

Version A:

        EditText et = new EditText(this);

        ArrayList<Object> x = new ArrayList<Object>(10);
        x.add(et);

        et.setTag(x);
        this.setContentView(et);

Version B:

        EditText et = new EditText(this);

        et.setTag(R.id.tag, et);
        this.setContentView(et);

test method

I run both versions on my phone, and I rotate my phone several times to cause the activity to stop and create again. Last, I force the GC to work (using heap view of Eclipse) and MAT to view the heap dump. If memory leakage does happens, the activity and the EditText will never get GC.

Result

version A

Version A is fine, even the circular reference is not too direct, it still managed to gc and only one instance of the Activity is present.

Android leaking memory in View.setTag()

Version B

On the other hand, Version B leaves a number of copies of Activity in memory (well, exactly the same as the times I rotated the phone). That means, it never get gc.

Implication

In the setTag(int, Object), never put any object that contains strong reference to the View itself (ie, if the View is a Group, don’t put reference to any child of the View as well). Although I starred the issue in Android Issue page, they had a “good” reputation for NEVER solving issues on that page; but as usual, I still urge everyone read about this to go and star it.

Advertisements