Reputation: 6268
I am getting the 'java.lang.OutOfMemoryError: bitmap size exceeds VM budget' error... What I am doing is that I download ~50 images from server and store them in the memory.
When I first saw this problem I optimize our images to download thumbnails only (50 JPEGS, ~12kB each, size 160x240px) and I start releasing them by calling Bitmap.recycle() as soon as I do not need them. Everything is working on newer phones, where the process can get 32MB, but on older phones with 16MB max not.
So my questions are:
Is it correct that all processes are limited to 32MB or less on older phones (i.e. the memory the Runtime.getRuntime().maxMemory() call returns) and this memory is for the Dalvik, framework, application and data?
Can we use more memory in application then amount returned by Runtime.getRuntime().maxMemory() ?
How I should optimize the images - they are anyway pretty small now... Should I start swapping them to internal flash/SD? I am keeping them in memory as long as they are shown in the GridView...
I appreciate any help - I went through the similar thread here and done what I have seen there... but still it is not enough...
Edit update
I added those comments after weakwire
answer.
• In my case I download ~50 images and store all of them in Bitmap objects in memory. See below why I am doing that.
• How much memory occupies the image in the Bitmap object? Is it there in raw format means that if image is 160x240x24bpp
it occupies ~115 kB
in memory, so 50 images are ~6MB
? Is that correct?
• I have also read that images are not part of my process heap, but they are counted, so using the maxMemory(), totalMemory(), freeMemory() cannot really help. Is that correct?
• My application UI has complete custom graphics (60 png files, many of them in draw9pacth format)
• I have no problem on 24/32 MB devices, I have problem only on 16 MB devices
• As soon as I download all 50 images and store them into memory I show them in the 2 columns width GridView. I think for this I need to keep all images on the heap (saving to internal flash I think is not solution there). Is that correct assumption?
• When I initialize the application and the UI is loaded I can see that I have 448kB free memory of 5459kB allocated of the whole 16384kB budget. I assume I cannot really use the whole 16384kB + if I understand it correctly I cannot really see from maxMemory(), totalMemory(), freeMemory() how much images that are already loaded occupy, since the dalvik-vm does not 'see' this heap. Assuming that ~2M are already used and I can use up to ~14MB I have 5.5MB left, so I can easily with 50 images in the memory run into OOM problems… Is that correct computation?
I WILL definitely go over the suggested video – it looks nice – but weakwire
, please try to answer me my questions… Thanks for that and for your time!
Upvotes: 1
Views: 966
Reputation: 9300
android:largeHeap="true" is out of the question. If not done correctly you will have a non crashing but SLOW application.
32MB VM is large. Many modern phones still use 12MB or 16MB. Larger != better.
It doesnt matter where you put the images. The only think matters is if they are in VM.
NO Runtime.getRuntime().maxMemory() is MAX memory you can use.
Bitmaps are nusty object(as far it's pixels reference not the Bitmap object itself). If not deallocated properly the GC cannot collect them and you get OutOfMemoryError.
now for you situation. 5MB of images should not cause a OOME. You have a memory leak or another large blocking object ( large background image maybe). You should check MAT and this video. There are ways that you can tell the garbage collector to collect the bitmaps but your problem i think can be avoided easily. 5MB of images are just fine and can be managable.(You don't need to show all 50 at once?Do you?)
Notes after your edit
I have also read that images are not part of my process heap, but they are counted, so using the maxMemory(), totalMemory(), freeMemory() cannot really help. Is that correct?
No.Images are part of the heap but not shown in MAT and other tools. I think they are visible only for 3.2 up but bitmaps are there.
As soon as I download all 50 images and store them into memory I show them in the 2 columns width GridView. I think for this I need to keep all images on the heap (saving to internal flash I think is not solution there). Is that correct assumption?
No that assumption is not correct and this assumption is what's causing the problem.
Why you need them all to the heap? You can have lagfree UI with the iamges at a storage device (SD or internal memory-cache).You have to LazyLoad your images if you are not sure how to handle them without lazyLoading.You should check the code of some popular image(down)Loaders and see how they handle references and how their caching system is organized. Also you can use one of them
Upvotes: 2