Android Memory Leak in createFromAsset() Method

Hi guys,

We are about to ship an Android application at my company, and I decided to do some memory analysis before we ship it, for a better performance. I was trying to investigate memory leaks, and one detail grabbed my attention.

You can print your app’s memory allocation typing this command in Terminal:

adb shell dumpsys meminfo <package_name|pid> [-d]

So I put this command and it printed that:

Output of memory analysis

Output of memory analysis 

Nothing seems extraordinary here. When I scroll down I saw that:

Output of memory analysis - Asset Allocations

Output of memory analysis – Asset Allocations

 

Investigating Your RAM Usage page of android gives an example output from Maps application, but they don’t have Asset Allocations section in their example.

In the first output, I counted number of asset allocations and it showed 30 allocations. I continued to use application by closing/opening new activities/fragments and the number was growing. In the example it is 93, but after the screenshot I reached 165 allocations.

The Problem

The problem is that every time I call createFromAsset() it was creating a new asset and keeping a reference to it. I searched the problem online and I found the following Stack Overflow post:  Investigating Android Memory Info.

The answer had a link to the issue reported in Android Open Source Project.

I read the issue and all comments. They claimed that it was fixed in 3.2.4. However, I am using 6.0.0 and seeing the same issue.

The Solution

One user on this page found a work around caching assets and it works fine for now. Until they actually fix it, this is the best we can do I believe:

public class Typefaces {
private static final String TAG = "Typefaces";
private static final Hashtable<String, Typeface> cache = new 
Hashtable<String, Typeface>(); 

    public static Typeface get(Context c, String assetPath) {
    
    synchronized (cache) {
            if (!cache.containsKey(assetPath)) {
                try {
                    Typeface t = Typeface.createFromAsset(c.getAssets(),assetPath);
                    cache.put(assetPath, t);
                } catch (Exception e) {
                Log.e(TAG, “Could not get typeface ‘” + assetPath + "' because " + e.getMessage());

                return null;
                }
            }

            return cache.get(assetPath);
        }
    }
}

In the past, I have seen this problem being reported on Stack Overflow, and I thought it was fixed. Apparently, the bug is still around. There are several blog posts/SO answers about this issue, this post is intended to show how we can catch it without doing deep investigation in Eclipse MAT.

Comments are closed.