1

I have an app running OOM with plenty of free heap space free and available to grow on a stock Galaxy S3. The app runs fine on other devices.

Knowing that in traditional Java this can be caused by being OOM within the permanent generation space, I tried looking into how Dalvik handles this, but couldn't find anything definitive. Androids SDK seems to be missing both MemoryUsage and ManagementFactory, so I can't get them as you would in Java.

I'm trying to find out if Android has a permanent generation space, can I inspect its contents, how can I get the size and free, does Dalvik handle what goes into this space different than JVM, etc.

Also open to other ideas if this space doesn't exist or it's not likely.

A bit of info on the app. The S3 that is running OOM is running 4.1.2. The app uses roughly 12-25 MBs of heap with the max heap size available being around 45MBs. It has a lot of local resource images, and lazy loads many more later on. I'm .recylce()ing the bitmaps. The app crashes in roughly the same spot every time. I've gave a good look at the code around the spot that crashes and I'm not seeing anything out of the ordinary. Other devices run this code just fine.

kireol
  • 703
  • 1
  • 9
  • 22
  • Post the error messages from the OOM – David Wasser Jul 01 '13 at 15:39
  • @David 07-01 14:09:16.936: D/dalvikvm(22514): GC_FOR_ALLOC freed 1432K, 48% free 34247K/64711K, paused 44ms, total 46ms 07-01 14:09:16.996: D/dalvikvm(22514): GC_BEFORE_OOM freed 31K, 48% free 34216K/64711K, paused 52ms, total 52ms 07-01 14:09:16.996: E/dalvikvm-heap(22514): Out of memory on a 1222696-byte allocation. – kireol Jul 01 '13 at 18:16
  • Well, that doesn't make any sense. The message says you have 30MB free, but fails on a 1.2MB allocation. Very strange. Most questions about OOM on Galaxy S3 indicate that you need to have your graphics in the `drawable-xhdpi` folder, otherwise they get scaled up which consumes lots of memory. You could at least check that. Otherwise, you could try setting `android:largeHeap="true"` in your manifest in the `` tag. Just some ideas. – David Wasser Jul 01 '13 at 18:27
  • making heap large "Fixes" the crash. But my understanding is that using that is bad practice. I did make sure all images are in xhdpi. I even went as far as loading up the biggest ones in photoshop and optimizing them. Still crashing – kireol Jul 01 '13 at 18:33
  • Doc on heap analysis tools: http://android-developers.blogspot.in/2011/03/memory-analysis-for-android.html – P.T. Jul 02 '13 at 16:47

1 Answers1

1

It seems to me that you're experiencing a heap fragmentation issue.

You are failing on a 1.2MB allocation in a heap that has plenty of free space. The system probably cannot find a continuous empty chunk of 1.2MB since your heap is completely fragmented, and it can't enlarge your heap further.

Theoretically, you're not supposed to worry about fragmentation issues and the automatic GC handles it for you..

Practically, I've seen more than once that giving the system GC a helping hand sometimes achieves magnificent results.

Here are some ideas to work around fragmentation issues:

  1. Run System.gc() manually in strategically placed locations. Popular locations are during destruction of large objects like activity onDestroy. Other place is before large allocations like Bitmaps. Before you decode any large bitmap, add a manual GC. If you want to reduce the number of GCs later, add an manual test for problematic memory conditions by querying the various heap size functions.

  2. Assist the System GC free resources faster. This will prevent your heap from becoming fragmented in the first place. Plenty of material on the net on how to do that. Some from the top of my head:

    • If you have frequent small allocations, try to adopt a memory reuse scheme like making a pool of objects, and reusing objects in the pool instead of allocating new ones. This optimization is often seen in android adapters (like view reuse in listviews)
    • Manually set variables to null when you don't need them in order to explicitly disconnect them from the reference graph and mark them for easy GC (same goes for explicitly clearing data collections)
    • Avoid immutable classes when you have plenty of operations, like concatenation of strings, use StringBuilder instead of regular Strings
    • Avoid finalizers completely
    • Avoid circular references, or at least change one of them to a weak reference
    • Use weak references in general where they're needed

You can measure how successful you are by making sure your heap does not grow to huge sizes when you're only using a small part of it.

Another idea is to try and make the 1.2MB allocation smaller.. By using smaller images or rescaling them during decoding.

talkol
  • 12,564
  • 11
  • 54
  • 64