I have been trying to fix a memory leak in my app for a long time, and I keep running into dead ends. The app is heavily image-centric, so I use the Picasso library to handle caching and memory use. I passed the high ram use (up to 100-170mb for my app) to bad memory management on Picasso's part, but I did some testing and disabled memory caching for Picasso, which loads all my images, and there was not a very noticable drop in RAM usage. It was still using 90 to upwards of 170 mb of RAM. I did a full heap dump into a hprof file and opened it with MemoryAnalyzer to see this:
http://i.gyazo.com/6b8d884852fa7cae546fc4cad1fc44c9.png.
If I go to Path to GC Roots, it shows no roots and no parents. There is no link to any of these over 50,000,000 bytes in these 25 massive byte arrays, and I really don't know where to start looking for the cause of it.
Do you have any suggestions on what the bug could be and any possible fixes?
Thank you very much for helping me out!
Try to use LeakCanary to find the memory leak.
Also, you can try Fresco for image loading & displaying, it stores images in the native memory region, so you won't use too much memory from the managed region, GC won't take too much time and you could avoid OutOfMemoryErrors.
Related
I was investigating the memory consumption of my android app. Immediately after app startup, I clicked 'Dump Java Heap' and the first class on the list is FinalizerReference (java.lang.ref). It has over 800 instances and consume more than 70% of the total memory comsumption.
I understand it is for garbage collection. Unlikely it is because of memory leak since it was captured right after app startup without switching to another view. I did not do any heavy processing during startup, apart from reading something from the shared preference.
Possible Memory leak through FinalizerReference
From this post, I tried to look on the referent field of the FinalizerReference, but it appears to be something that beyond my understanding e.g. Matrix, Canvas, Render Node. It sounds like UI components for me.
Here is my question:
Is there any way/tool for me to further debug the root cause of memory comsumption.
Is this something that I need to worry, or it is just the normal behavior of android memory management.
A better tool would be useful, but only because it should show that the reported Retained Size of ~33 MB for FinalizerReference is not real memory consumption, just massive multiple counting of the same small amount of memory by the Memory Profiler. The Shallow Size of ~28 kB is important, but negligible. The way I investigated this (using Memory Profiler) is detailed in my answer to my own similar question.
You should not worry about FinalizerReference, at least not based on what you show here. You may need to worry about Memory Profiler, due to the meaningless Retained Size it reports for this class. I regard its calculation as a bug, and I filed this issue.
I'm using vectordrawable for displaying images. The images are all resources which are bundled with the app (apk). My problem is, that the memory on every new activity massivly get higher until the app crashes with an OutOffMemoryException.
java.lang.OutOfMemoryError
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:903)
at android.graphics.Bitmap.createBitmap(Bitmap.java:880)
at android.graphics.Bitmap.createBitmap(Bitmap.java:847)
I've looked into MAT for memory leaks, but did'nt find out any more than the bitmap errors.
What are the efficients way to display vectordrawables? Maybe the general architecture of my app isnt right with the activity lifecycle?
I didn't find any informations about the common memory ussage of other apps (facebook, aibnb, whatsapp,..). My usage is around 40-70MB.
There are a few things to be careful about when dealing with images:
Are you loading your images every time when you show them? This can be a potentially very memory consuming operation. It's better to load the images into memory once and then reuse them across the app.
Are you cleaning the memory occupied by the images you no longer use? If you are sure that an image is no longer needed, you should clean the allocated bitmap memory by calling bitmap.recycle(). This invalidates the bitmap and frees all the occupied memory, making it available for other operations.
Are the images too large? There is a limit for the maximum size of a single image. Trying to load a bigger image will also cause an OutOfMemoryError, even though memory can be available. In that case, you may want to optimise the image files that you are trying to load.
Go though your app and check for those potential problems one by one. Also, there are good profiling tools available for the Android platform. They can show you potential problems with the memory management, like excessive memory allocation, etc.
Good luck.
OOM happens when the heap gets full. But what if we increased the size of the RAM of the device, will that help prevent OOM?
I tried to look at tutorials on how to prevent OOM , which recommended multi-threading and trimming down the size of the bitmap. But I still get OOM errors.
But what if we increased the size of the RAM on the device, will that help prevent OOM?
Yes and no. The answer is "it depends on why you are running out of memory."
If you are trying to manipulate a 2GB Bitmap on a 1GB device, then yes, adding a few extra GB of RAM will solve your problem.
If you have a rogue operation that is constantly allocating new Objects, then adding additional memory will just delay the OOM Exception. Extra RAM is not a long term solution to poor memory management.
You need to work to identify why you are running out of memory first. If the issue is that you really do need more RAM (which is fairly unlikely), then go ahead and add more. If the problem is that you are unnecessarily allocating memory or leaking objects, then fix those problems first.
With Bitmaps specifically, you often don't need the full quality image. If your image is stored at 1080p resolution but the device is only a 480p screen, then loading the entire image into memory is a waste of space since most of the image won't be used anyway.
I have an android app that uses alot of memory doing pixel manipulation. And what I have noticed is that android does not kill programs or free memory in favor of the foreground app. And my app just crashes with not enough memory errors. Right now I have it autodetect how much memory is left and scale pictures appropriately. This prevents crashes but results in poor image quality.
Is there a way to tell Android OS, free up memory as my app is memory hungry. From what I read from android, the OS should do this automatically. But it doesn't appear to do it. Maybe I'm missing something? The iPhone seems as it handles this much better.
Android apps have a hard Java heap limit which varies between devices. 24MB is a typical amount.
So the obvious workaround is to not allocate your big objects in Java... you can malloc your pixel byte arrays from a native C method instead.
However 24MB ought to be enough for anybody, to borrow a phrase, so I recommend you try to rethink your approach too. Perhaps be more aggressive about reusing bitmaps from a fixed-size pool, break your images up into smaller tiles, etc etc.
Avoid using getPixel() and setPixel() too much, it hence results in a really really bad performance, it's already mentioned on Android Documentation.
Also, manage your own memory usage Java, Garbage Collector will function as long as you follow the rule.
I am working on an application for android and we since we have lots of graphics, we use a lot of memory.
I monitor the memory heap size and its about 3-4 Mb , and peeks of 5Mb when I do something that requires more memory (and then goes back to 3). This is not a big deal, but some other stuff is handled outside the heap memory, like loading of drawables.
For example if I run the ddms tool outside eclipse, and go to sysinfo, I see that my app is taking 20Mb on the Droid and 12 on the G1, but heap size are the same in both, because data is the same but images are different.
So the questions are:
How do I know what is taking the memory outside the heap memory?
What other stuff takes memory outside the heap memory? Complex layouts (big tree) ? Animations?
Thanks
Daniel
Bitmap objects takes a quite alot of memory.
Ex. if your app downloads a 10KB jpg from net and use BitmapFactory to decode it into a Bitmap that bitmap objects needs about 30-100KB memory, depending on the resolution of your image. 3bytes for each pixel (1 byte for each color)
And yes, all kind of object uses memory, like LinearLayouts, ImageViews etc... If you are creating and destroying many of these objects, ex. as you scroll / page through your images, there will be memory leaks. The gc() does not handle so-called short lived objects as fast as we would like.
*Keep the number of view objects at a stable level**, and recycle them instead of destroying and creating new ones.
REf: http://developer.android.com/resources/articles/track-mem.html
If your app reaches 20MB in memory, it may FC as the BitmapFactory is trying to decode the next image.
One obvious candidate is off course off-screen bitmaps (double-buffering by android?), since the screensize has ~4x as many pixels on the droid.