0

Android Memory Usage Problem on possibly using ActivityGroup

This is a little bit long story that i ended up messing with memory problems. I developed very deep android application by using very amount of Activities and Frameworks. First of all I have to say I used ActivityGroups for main categories to handle activities easily. And I can achieve all activities via getLocalActivityManager(). And I get this error message:

02-25 11:34:13.749:
ERROR/dalvikvm-heap(3042):
2764800-byte external allocation too
large for this process.

02-25 11:34:13.749:
ERROR/GraphicsJNI(3042): VM won't let
us allocate 2764800 bytes

then my application will crash with various exceptions, eg;

02-25 11:34:13.772: ERROR/AndroidRuntime(3042): FATAL EXCEPTION: main
02-25 11:34:13.772: ERROR/AndroidRuntime(3042): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.turkcell.seyahat/com.matriksdata.ui.schedule.MessageDetail}: android.view.InflateException: Binary XML file line #2: Error inflating class <unknown>
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.app.ActivityThread.startActivityNow(ActivityThread.java:2503)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.app.LocalActivityManager.moveToState(LocalActivityManager.java:127)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.app.LocalActivityManager.startActivity(LocalActivityManager.java:339)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at com.matriksdata.app.XActivityGroup.goForward(XActivityGroup.java:122)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at com.matriksdata.ui.parents.ScheduleActivityGroup.goForward(ScheduleActivityGroup.java:143)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at com.matriksdata.ui.schedule.MessageBox.onItemClick(MessageBox.java:81)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.widget.AdapterView.performItemClick(AdapterView.java:284)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.widget.ListView.performItemClick(ListView.java:3730)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.widget.AbsListView$PerformClick.run(AbsListView.java:1808)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.os.Handler.handleCallback(Handler.java:587)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.os.Handler.dispatchMessage(Handler.java:92)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.os.Looper.loop(Looper.java:123)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.app.ActivityThread.main(ActivityThread.java:4627)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at java.lang.reflect.Method.invokeNative(Native Method)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at java.lang.reflect.Method.invoke(Method.java:521)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:871)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:629)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at dalvik.system.NativeStart.main(Native Method)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042): Caused by: android.view.InflateException: Binary XML file line #2: Error inflating class <unknown>
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.LayoutInflater.createView(LayoutInflater.java:513)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:563)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.LayoutInflater.inflate(LayoutInflater.java:385)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:210)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.app.Activity.setContentView(Activity.java:1647)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at com.matriksdata.ui.schedule.MessageDetail.onCreate(MessageDetail.java:33)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     ... 18 more
02-25 11:34:13.772: ERROR/AndroidRuntime(3042): Caused by: java.lang.reflect.InvocationTargetException
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.widget.LinearLayout.<init>(LinearLayout.java:115)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at java.lang.reflect.Constructor.constructNative(Native Method)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at java.lang.reflect.Constructor.newInstance(Constructor.java:446)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.LayoutInflater.createView(LayoutInflater.java:500)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     ... 28 more
02-25 11:34:13.772: ERROR/AndroidRuntime(3042): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.graphics.Bitmap.nativeCreate(Native Method)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.graphics.Bitmap.createBitmap(Bitmap.java:435)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:340)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:590)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:564)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:425)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.content.res.Resources.loadDrawable(Resources.java:1709)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.View.<init>(View.java:1885)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.View.<init>(View.java:1834)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.ViewGroup.<init>(ViewGroup.java:285)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     ... 32 more

Of course i don’t have 2764800 byte png image, but i think its decoded size. So i thought that i had image handling problems and i checked and fixed my project in every detail to handle images correctly. I checked everything described in android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html . I checked null drawables, i follow model reusability instructions, i changed loading methods described in : stackoverflow.com/questions/477572/android-strange-out-of-memory-issue/823966#823966.

Also i have few bitmaps to load from disk. My all layouts created by android xml layout files. I have plenty of bitmaps described in xml files also.

Then i saw that i have big static classes in application with memory analyzer. i freed that static properties by loading on demand and freeing after used. So finally i got this memory leak suspects in MAT;

Problem Suspect 1

3,043 instances of "java.lang.Class", loaded by "" occupy 871,304 (17.97%) bytes.

Biggest instances:
class com.ibm.icu4jni.util.Resources$DefaultTimeZones @ 0x4014c3b0 - 166,768 (3.44%) bytes.
class android.text.Html$HtmlParser @ 0x400fe448 - 126,592 (2.61%) bytes.
class com.google.googlenav.proto.GmmMessageTypes @ 0x4835d450 - 56,944 (1.17%) bytes.
class org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionPool @ 0x47caea20 - 51,872 (1.07%) bytes.
class org.apache.harmony.security.fortress.Services @ 0x4008c4d0 - 51,456 (1.06%) bytes.

Problem Suspect 2

8,721 instances of 'java.lang.String', loaded by 'system class loader' occupy 549,624 (11.33%) bytes. 

Keywords
java.lang.String

Problem Suspect 3

60 instances of "org.bouncycastle.jce.provider.X509CertificateObject", loaded by "system class loader" occupy 300,024 (10.76%) bytes. These instances are referenced from one instance of "java.util.Hashtable$HashtableEntry[]", loaded by "system class loader"

Keywords
org.bouncycastle.jce.provider.X509CertificateObject
java.util.Hashtable$HashtableEntry[]

This third one not occurs every time. Generally when i use memory manager in GalaxyTab.

My biggest Top-level Dominator Classes are these. http://www.matriks.mobi/arge/android/Screen%20shot%202011-02-25%20at%2012.19.08%20PM.png

I have just 2 or 3 activities live and the rest of them are suspended. I get this messages in components report. Of course this is not the explanation that i use just 1.5 MB of ram, because according to memory manager my application uses 48 MB of ram up from about 20 MB.

Possible Memory Waste * Duplicate Strings* Found 0 occurrences of char[] with at least 10 instances having identical content. Total size is 0 bytes.

i think thats not the thing that i want :) hprof file located in http://www.matriks.mobi/arge/android/android5706014442078310727.hprof.zip

I am guessing that i have problem with ActivityGroup class. At least i am keeping activities and activity ids in LocalActivityManager in stacks. But even if i don’t create new activities, and passing between loaded ones, memory increases.

I know this is not the way of searching for leaks, and possibly i have a code based problem causing this memory leaks. But any single idea that i should check will be very very welcome here, because i am kinda stuck here.

Alkimake
  • 1,797
  • 14
  • 30
  • Edit: I have found the problem. I was resetting background image everytime activitygroup created by; `background.setBackgroundResource(R.drawable.background);` I removed this and left the description in xml, so problem solved. This method causes memory leaks. – Alkimake Mar 01 '11 at 14:27

3 Answers3

2

Try tracking memory allocations while application is in use.

Also, holding references to Bitmap Drawables can produce memory leaks. When a Drawable is added to View, a circular reference is created. So when you hold a reference to Bitmap drawable, it further holds a reference to a View and this View can never be GCed.

The easiest way to avoid it is to extract a bitmap from a Bitmap Drawable and hold a reference to it, then when Activity is restarted/reloaded, you create new Bitmap Drawables from this bitmaps. This is how a Photostream example works (described at the end): Faster screen orientation change

Mario Kutlev
  • 4,897
  • 7
  • 44
  • 62
Peter Knego
  • 79,991
  • 11
  • 123
  • 154
  • i am tracking memory allocations and i just see that heap size and percentage is increasing. I think that is why i can not see any drawable objects in memory allocations. As i wrote i use every single solutions in your referenced web sites. Nothing changed. – Alkimake Feb 25 '11 at 13:36
  • The link says: "As part of my job, I ran into memory leaks issues in Android applications and they are most of the time due to the same mistake: keeping a long-lived reference to a Context." Do you keep long-lived references to Activities inside ActivityGroup? Try using WeakReferences. – Peter Knego Feb 25 '11 at 13:41
  • I don't know if i can tell i dont keep long-lived references. But i try to get each activity with intent. And in memory analyzer i understand that i have maximum 3 live Activities. i am using weak hash map described in : http://www.ibm.com/developerworks/java/library/j-jtp11225/ – Alkimake Feb 25 '11 at 14:01
0

Do you use this layout for the rows of a ListView?

pedr0
  • 2,941
  • 6
  • 32
  • 46
  • 2764800 byte are not an incredible size for an image – pedr0 Feb 25 '11 at 12:11
  • in some activities yes. But generally no. And i believe that is not the issue, because even if i dont load any activity uses listview, memory increases 1-2 mb every time i go and back and passing through activity groups (each activity group has 1 activity initially). – Alkimake Feb 25 '11 at 13:12
  • 2764800 byte is not a big size for a png, but the biggest png file is 499,246 bytes in project – Alkimake Feb 25 '11 at 13:13
  • also i use LayoutInflater to create user controls from xml. Maybe it is the problem but i am not sure. i use `LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); layoutInflater.inflate(getId(), this, true);` for each control. – Alkimake Feb 25 '11 at 13:15
  • 499,246 bytes is the compressed size of the image, when you load it into memory will be uncompressed.Bitmap use Native Heap and not Dalvik heap for memory allocation, try to recycle them for fix the problem.Is very important to understand that Bitmap are allocated in Nativhe Heap and you cannot SEE THEIR memory on DDMS. (without a trick) – pedr0 Feb 25 '11 at 16:35
  • I think i found the problem. @pedr0 if you re-write first revision of your comment, we will continue from there and i will mark. – Alkimake Feb 28 '11 at 16:08
0

I was resetting background image everytime activitygroup created by;

 background.setBackgroundResource(R.drawable.background); 

I removed this and left the description in xml, so problem solved. This method causes memory leaks.

Alkimake
  • 1,797
  • 14
  • 30