I am trying to analyze the heap dump of my android app. The analyzer MAT shows
me this message
The class "android.content.res.Resources", loaded by "", occupies 12,084,776 (87.38%) bytes. The memory is accumulated in one instance of "java.lang.Object[]" loaded by "".
What do I do about this? I want to avoid OutOfMemoryError.
As almuneef mentioned, this is mostly seen when the size of your resources is large. Are you trying to load a bitmap?
You might want to look at Android memory allocation
Your problem is due to the large resources. Just reduce the size of your resources and your issue will be fixed.
If your resources are in .png format then change it to jpeg and you can easily reduce the quality of the image (size also reduces considerably for even a small loss in quality)
Hope this will fix your out of memory issues
Don’t worry about “android.content.res.Resources”,It was loaded by system,
Related
I have a screen where I have to show two similar images on screen . The size of both these images is dynamic but they covers most of the screen. When I navigate to this screen in my app, I see a spike of 12MB in Memory Monitor in AndroidStudio meaning both these images is using that 12MB as there is no other UI element on that screen and as both these images are similar takes takes equal amount of screen space, I guess each consumes 6MB of memory when shown. The dimensions of both these images are 1174 x 1174 pixels and the size is 396KB in res directory.
I have tried using Glide but I see same memory spike when these images are loaded through Glide too. Even Glide can't help if the app tries to take more memory than available and there is heavy usage of images in other parts of my app. So there is always memory crunch and I'm getting lot of OutOfMemory exceptions in the app where these two images are shown.
So my question is how can I reduce the memory usage of those images? Also why does the image takes 6MB of memory when it's size is 396KB in res folder?
I am guessing you did not compress your images, use https://github.com/zetbaitsu/Compressor very great at image compression. Also i am also guessing you did use Glide caching strategies.
Glide, however, caches the original, full-resolution image and additionally smaller versions of that image. For example, if you request an image with 1000x1000 pixels, and your ImageView is 500x500 pixels, Glide will put both versions of the image in the cache.
DiskCacheStrategy.NONE caches nothing, as discussed
DiskCacheStrategy.SOURCE caches only the original full-resolution image. In our example above that would be the 1000x1000 pixel one
DiskCacheStrategy.RESULT caches only the final image, after reducing
the resolution (and possibly transformations) (default behavior)
DiskCacheStrategy.ALL caches all versions of the image
To answer your answer you need to manually keep track of the cache volume in android.Try forcing an garbage collection,Normally, VMs perform garbage collection only when absolutely needed, since it’s expensive. However, it can be useful to force garbage collection in certain circumstances. For example, when locating memory leaks, if you want to determine whether a large object was successfully released already, you can initiate garbage collection much more aggressively than usual.
Hope this was helpful.
I'm writing a camera app and when I take a picture, I receive a byte [], decode it into a Bitmap and rotate it before saving it to JPEG. I'm rotating the photo using a native library, however the bitmap is still decoded from a byte[] into memory for this (still, allows me to keep 1 Bitmap instead of 2). So essentially there's 1 place in my code where I require a lot of memory and OOM on some devices where heap is low and cameras are stupid-megapixels. Any suggestions how to fix this without on loosing image quality?
I don't think I want to use largeHeap="true"
Should I forget about rotation and just set EXIF?
Also I'm not so keen on trying to 'predict' if I will OOM as the math's not adding up: Android OutOfMemory when GC reports free memory?
Any suggestions how to fix this without on loosing image quality?
Use android:largeHeap="true".
Or, use some other native library that allows you to hand over the byte[] and does the rotation and saving to disk for you, to avoid the Bitmap and any Java-level processing of the huge thing.
Or, if your minSdkVersion is 19, and the rest of your logic supports it, use inBitmap on BitmapFactory.Options to try to reuse an already-allocated Bitmap object rather than allocate a fresh one. This option is available on earlier versions of Android, but for those it has to be an exact match in terms of resolution; on 19+, the Bitmap to be reused just has to be big enough to handle what you are trying to load into it.
I don't think I want to use largeHeap="true"
It may not help (not all devices will give you a larger heap), and there are costs to the user for the larger heap limit. That being said, manipulating big camera images is difficult without more memory, whether that is in the Java heap or represents allocations from the OS from native code.
Should I forget about rotation and just set EXIF?
That's certainly another possibility, though various things, like ImageView, seem to ignore EXIF headers.
I'm not so keen on trying to 'predict' if I will OOM as the math's not adding up
In part, that's because Dalvik does not have a compacting/moving GC, and ART only has one while your app is not in the foreground. OutOfMemoryError means that there is no single contiguous free block of memory for what you are trying to allocate.
You might not have enough memory to create a rotated copy of a large bitmap.
You could instead paint a rotated image of the original.
Furthermore there are things that need to be considered when processing images:
Always load images scaled to the size of the ImageView.
Always recycle your images
Consider using largeHeap=true if you still have issues. Android might be growing the heap size too slowly (see https://stackoverflow.com/a/14462026/1390015).
I am Working with one android tablet application in which lots of work with Images.
i have to load hundred of large bitmap images in scroll view. one image is around 1Mb to 3 Mb.
i have already scale images using bitmap factory and sample size, and also load all the images in Async task.
i am loading all the images from SD card.
Still facing OUT OF MEMORY issue after scrolling some images.
any help would be appreciated.
thanks in advance.
hi hope your solution.
you can user Univarsal Image Loader. This is better api for image download and store in catch. and get from catch. it's a great api for image operation.
this case is often come while we getting bitmap so just use lazy loading. just take a look on this example
http://sunil-android.blogspot.in/2013/09/lazy-loading-image-download-from.html
To prevent your application from soaking up CPU time without getting anything done, the JVM throws this Error so that you have a chance of diagnosing the problem.
Its because of large bitmap memory in stored in native area
so it better i suggest you use libraries like Universal Image Loader or
Bitmap Fun from android
You have to find out when the OOM error occurs. Is it when you have too much bitmap cache in memory without releasing or you just meet it when you're decoding certain bitmap?
For the first situation, I think you should manage your bitmap cache yourself or using some effective 3rd-party library which mentions above.
For the second situation, I've met it on some low-performance mobile(usually with 512MB or less memory), when you decode a bitmap to requested size, it may needs a rather large memory to store the bitmap, for 240dpi devices, it's about 800 * 480 * 4 = 1.5MB, however you may fail to allocate that much memory on some machines cause they may have strict memory manage strategy to prevent that much memory allocation. You should just catch the OOM error and continue rather than get a crush.
Loading a bitmap in 1280x800 display will take 1280x800x4 byte (~4MB) memory. Java heap size is limited (~50MB) so you can not use lots of large bitmaps in your app. Using cache and reusing bitmap objects are necessary while working with bitmaps but another useful trick is to use larger hip size! to do so, add android:largeHeap="true" to Application tag in your manifest. It increases hip size to 4 or 5 times larger (~250MB) than normal. I hope this help other people reaching this thread while they search!
I've programmed an Android game in the past and had always run into memory issues because my images have been quite large ~(1000x400 px each). I'm now wondering if it is necessary to load images into memory solely as bitmaps. Is there any reason for not loading bitmaps in some loss-less compressed format?
I don't know much at all about image compression/decompression efficiency, but I assume that there would be performance issues. But I feel as though "simple" compression algorithms can't be too processor intensive, even if they only cut down the image to half of it's uncompressed memory footprint.
The problem is that at some level you must have pixel by pixel representation of the image, hence you must have a bitmap.
The best solution to this is to switch to a compressed graphics type that can be used by OpenGL, as answered on gamedev.stackexchange.com at thsi question:
https://gamedev.stackexchange.com/a/28463/8126
Unfortunately for me I have no experience in OpenGL.
I want to display a bitmap read from the SD card at actual pixel size in Android.
I can't assume anything about the bitmap, other than Android supports its image format. The bitmap might be huge.
Seems simple enough, but when you factor Android memory limitations it gets much more complicated.
Any ideas?
Edit: Attempting to load a large bitmap gives an out of memory error because Android is not able to allocate enough memory to decode it. You can load a scaled down version of the bitmap, but this is not useful to show the bitmap at actual pixel size. The question is about how to show a large bitmap on Android while staying within the app's memory constraints (most likely by loading it in chunks).
Edit 2: The bitmap might be huge, but within the realm of reasonable. I'm talking about user images, not HD Nasa pictures.
The managed code (Java) has memory limits of 16/24/32MB even if your device has a lot more free memory. I'm currently working on an application which needs to do this and the solution is to allocate the bitmap in native code (NDK) and then render views of the image into a Java-allocated bitmap which is the size of the display. In native code you can allocate all available memory of the device, but for some reason the virtual machine limits it.
Since android 2.3 (Gingerbread, API Level 10), you can use the BitmapRegionDecoder. I don't know any solution for older android versions. (and I've been looking for it for my EmailAlbum app)