As title says, I have out of memory exception being thrown on loading layouts. One would think this is a memory leak issue, but after battling it for 2 days I am not so sure anymore. The app has 10+ activities, most of which have background images.
Few facts/discoveries I made:
so far issue only appears on Galaxy Nexus running Android 4.0.3. I was unable to reproduce it on Nexus S (4.1.1) and Galaxy S II (2.3.3).
the screen orientation does not change. In fact most of my activities locked to portrait anyway.
just for laughs I added call to
finish()
when opening new activity, so there wouldn't be more than one activity in memory at the time. Verified thatonDestroy
is being called.
defined as:
@Override
public void onDestroy()
{
super.onDestroy();
cleanupDrawables(contentView);
// null all the fields referencing views and drawables
System.gc();
}
where cleanupDrawables()
is:
protected static void cleanupDrawables(View view)
{
cleanupDrawable(view.getBackground());
if (view instanceof ImageView)
cleanupDrawable(((ImageView)view).getDrawable());
else if (view instanceof TextView)
{
TextView tv = (TextView)view;
Drawable[] compounds = tv.getCompoundDrawables();
for (int i = 0; i < compounds.length; i++)
cleanupDrawable(compounds[i]);
}
else if (view instanceof ViewGroup && !(view instanceof AdapterView))
{
ViewGroup vg = (ViewGroup)view;
for (int i = 0; i < vg.getChildCount(); i++)
cleanupDrawables(vg.getChildAt(i));
vg.removeAllViews();
}
}
protected static void cleanupDrawable(Drawable d)
{
if (d == null)
return;
d.setCallback(null);
if (d instanceof BitmapDrawable)
((BitmapDrawable)d).getBitmap().recycle();
else if (d instanceof LayerDrawable)
{
LayerDrawable layers = (LayerDrawable)d;
for (int i = 0; i < layers.getNumberOfLayers(); i++)
cleanupDrawable(layers.getDrawable(i));
}
}
looking at the Eclipse heap inspector, memory appears to be stable, i.e. some activities take more memory than others, but it is released upon closing, and it appears stable over time.
according to related answers on SO images are stored in native memory, but this dude claims they should be on the heap since Android 3, so I should see memory increase if this was indeed image memory leak.
The end result of my efforts is that I still get out of memory error, though not as fast as I did before. Before error occurs I begin to see visible bitmap corruption, which wasn't the case before I added the cleanupDrawables()
code. I deduced that call to Bitmap.recycle()
is causing corruption, even though this code is only called on onDestroy
. Corruption appears on both bitmaps that are parts of common styles appearing on many activities as well as bitmaps only shown on one activity.
In short results of my investigation are rather inconclusive. At this point I don't know what else to try.
The error stack trace for reference:
08-22 10:49:51.889: E/AndroidRuntime(31697): java.lang.RuntimeException: Unable to start activity ComponentInfo{klick.beatbleeds/klick.beatbleeds.Bleeds}: android.view.InflateException: Binary XML file line #67: Error inflating class <unknown>
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1955)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1980)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.app.ActivityThread.access$600(ActivityThread.java:122)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1146)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.os.Handler.dispatchMessage(Handler.java:99)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.os.Looper.loop(Looper.java:137)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.app.ActivityThread.main(ActivityThread.java:4340)
08-22 10:49:51.889: E/AndroidRuntime(31697): at java.lang.reflect.Method.invokeNative(Native Method)
08-22 10:49:51.889: E/AndroidRuntime(31697): at java.lang.reflect.Method.invoke(Method.java:511)
08-22 10:49:51.889: E/AndroidRuntime(31697): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
08-22 10:49:51.889: E/AndroidRuntime(31697): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
08-22 10:49:51.889: E/AndroidRuntime(31697): at dalvik.system.NativeStart.main(Native Method)
08-22 10:49:51.889: E/AndroidRuntime(31697): Caused by: android.view.InflateException: Binary XML file line #67: Error inflating class <unknown>
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.LayoutInflater.createView(LayoutInflater.java:606)
08-22 10:49:51.889: E/AndroidRuntime(31697): at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.LayoutInflater.onCreateView(LayoutInflater.java:653)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:678)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.LayoutInflater.rInflate(LayoutInflater.java:739)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
08-22 10:49:51.889: E/AndroidRuntime(31697): at klick.beatbleeds.ActivityBase.setContentView(ActivityBase.java:82)
08-22 10:49:51.889: E/AndroidRuntime(31697): at klick.beatbleeds.Bleeds.onCreate(Bleeds.java:40)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.app.Activity.performCreate(Activity.java:4465)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1919)
08-22 10:49:51.889: E/AndroidRuntime(31697): ... 11 more
08-22 10:49:51.889: E/AndroidRuntime(31697): Caused by: java.lang.reflect.InvocationTargetException
08-22 10:49:51.889: E/AndroidRuntime(31697): at java.lang.reflect.Constructor.constructNative(Native Method)
08-22 10:49:51.889: E/AndroidRuntime(31697): at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.LayoutInflater.createView(LayoutInflater.java:586)
08-22 10:49:51.889: E/AndroidRuntime(31697): ... 23 more
08-22 10:49:51.889: E/AndroidRuntime(31697): Caused by: java.lang.OutOfMemoryError
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.graphics.Bitmap.nativeCreate(Native Method)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.graphics.Bitmap.createBitmap(Bitmap.java:605)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.graphics.Bitmap.createBitmap(Bitmap.java:551)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:437)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:524)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:499)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:351)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:773)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.content.res.Resources.loadDrawable(Resources.java:1937)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.View.<init>(View.java:2780)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.view.ViewGroup.<init>(ViewGroup.java:385)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.widget.LinearLayout.<init>(LinearLayout.java:174)
08-22 10:49:51.889: E/AndroidRuntime(31697): at android.widget.LinearLayout.<init>(LinearLayout.java:170)
08-22 10:49:51.889: E/AndroidRuntime(31697): ... 26 more
Here is a screenshot of one of the views to get the idea of how many images are used here