DDMS Heap - 1-byte array(byte[], boolean[]) - android

I experience some memory leaks in my android application. I've already used MAT to analyze the memory usage. But I have one question from the DDMS perspectiv in Eclipse, what does 1-byte array[byte[], boolean[]) mean?
Is this specific for my application? You can see that this is the big memory leak issue, this always increases in size, and the rest will increase and decrease randomly. My guess is that the GC doesn't catch this type. Can anybody explain why this happen, with this little information?

One byte array is the designation for any data structure that is organized as a single byte array. In you case and with that size, I would bet in a Bitmap or a Drawble.
Most common reasons for memory leaks are static object not properly managed and holding references to:
Context
View (which holds reference to context (and possibly also to bitmap)
Thread (which are not easly collected by GC)
Handler (which holds reference to context)
Most of them can be solved ensuring that you set the object to null when it's no long required.
Regards.

A byte and a boolean are each 1 byte. If you have an array of those you have a "1-byte array".
A ByteBuffer for example should internally hold one of those.
You have a total of 614 of them where the smallest one be a byte[24] (or boolean[24]), the largest one is 3MB. All of them together use 104MB.
The GC will get rid of them if they are no longer referenced.
For example when you put
private static byte myArray[] = new byte[3 * 1024 * 1024];
in one of your classes and never set it back to null (myArray = null) then this one can't be garbage collected because another Object has a reference to it. The object would be the class itself (as in String.class). The class object can't be garbage collected since classes are never unloaded. (they are referenced by their ClassLoader which could itself be referenced / loaded by another ClassLoader and you can't create Objects & use classes without them - they need to stay and they need to keep a reference to their classes)
It's usually not that simple but often start with static somewhere.
Within MAT (after you force GC) look at the reference chain for the objects that are no longer intended to stay alive and identify the one Object that holds the reference. Set that one to null in your code and your leak is gone. Explained in more detail here:
http://android-developers.blogspot.de/2011/03/memory-analysis-for-android.html

I ran to this problem tonight and almost I checked every bit of code but I couldn't find anything.
What I did was starting the app from intelij and then pressing home button and open the app again. Every time the app heap was doubled.
Finally I discover when I launch the app from ADB and press the home button and open the app again it doesn't bring back the old activity, it just start a new one. When I pressed finish it starts to cycle through all of them. It's like they are treated as two different intent. So I put android:launchMode="singleTop" on the main activity in manifest and it resolved the problem.
Although it's not the main cause of this problem but if you encountered this check this out before anything. It wasted three or four hours for me.

Related

Why is this a memory leak

I came across a library for memory leak detection in Android (Java) called LeakCanary but cannot understand the example where they leak the memory. Could anybody please explain how and why the code shown in their example is a memory leak.
class Cat {
}
class Box {
Cat hiddenCat;
}
class Docker {
static Box container;
}
// ...
Box box = new Box();
Cat schrodingerCat = new Cat();
box.hiddenCat = schrodingerCat;
Docker.container = box;
and then they watch the variable schrodingerCat for leaks which gives a leak shown as follows (which I dont know how to relate to the above code).
* GC ROOT static Docker.container
* references Box.hiddenCat
* leaks Cat instance
Any help with the explanation of the leak and how the detection relates to it would be very helpful. Also some good articles for beginners would be nice.
Thanks!
First, let's understand what is a Memory Leak:
Definition
Memory Leak is data allocated (bitmaps, objects, arrays, etc) in the RAM that the garbage collector (GC) is unable to free, although it is not needed anymore by the program.
Example
A user is opening a view that shows an Image. We load the bitmap to the memory. Now the user exit the view and the image is not needed anymore and there is no reference to it from the code. At that moment the GC comes into action and remove it from the memory. BUT, if we still had a reference to it, the GC will not know it is OK for removal and it would have stayed in the RAM taking unneeded space - aka Memory Leak.
Cat in A Box
Let's say we have a Cat object in our app, and we hold it in a Box object. If we hold the box (have a reference to the Box object) and the Box holds the Cat, the GC will not be able to clean the Cat object from the memory.
The Docker is a class that has a Static reference to our Box. This means that unless we nullify it, or re-assign the value, the Docker will keep referencing the Box. Preventing the Box (and the inner Cat) from ever being removed from the memory by the GC.
So, do we need the Cat? is it still relevant for the App?
This is up to the developer to decide how long we need the Cat for. LeakCanary and other diagnostic tools suggest of a possible Memory Leak. They THINK that the object (Cat) might not be needed anymore so they alert that it is a leak.
Recap
In the example, they give a common scenario of a Memory leak. When using a Static reference we prevent from the GC to clean an Object. You should read this:
* GC ROOT static Docker.container
* references Box.hiddenCat
* leaks Cat instance
as:
Object Cat might be not used anymore but was not removed from memory by the GC.
The reason the object Cat was not removed is since Box is having a reference to it.
The Reason the object Box was not removed is since the Docker has a static reference to it.
Static reference by Docker is the ROOT of the tree that causes the possible leak.
It looks like the RefWatcher instance used to "watch the variable schrodingerCat for leaks":
refWatcher.watch(schrodingerCat);
forces a set of GC passes and if the reference passed in isn't collected during those GC passes it's considered a leak.
Since the static Docker.container.hiddenCat is keeping a GC rooted reference to the object originally known as schrodingerCat, it can't be GC'ed so when you ask RefWatcher to check it. Therefore it lets you know that the object can't be collected.
I suggest you read this answer https://stackoverflow.com/a/11908685/1065810
It will probably help you understand the example above.
In brief, in your example, the class Docker keeps a reference to a Box. Even when the container box is not needed anymore, the class Docker still holds a reference to it thus creating a memory leak.
Let me know if that helps.

Best way to cache in memory a single Bitmap shared across instances

To draw my sprites in OpenGL i use a single backing bitmap across multiple objects, the Bitmap is reused if size is big enough or recreated if too small. Currently i am using a static Bitmap object but i think this is causing memory leaks even if i am not sure about that.
So, let's say i need a single Bitmap shared between multiple objects, what would be the best approach?
1) Use a single Bitmap as a static reference as i do
2) Use a static weakreference (even if its not suggested in the android dev page here http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html)
3) Use a singleton and then a Bitmap inside it (but this would be like 1)
4) Use an LRU cache and just creating a new bitmap every time i need it to be bigger
1,3 & 4 are essentially all the same. You create a static reference to either your Bitmap directly or to something that holds a reference. The same happens when you use the Application class to "anchor" that bitmap. That class is kept by Android alive and is in this context the same as a static reference.
Whether this is a memory leak or not depends on your definition. Leaked objects are those that are kept safe from the garbage collector by unintentional references to them. So it's certainly not a leak while you want that reference to keep your bitmap.
The problem that arises with cached data that is independent of the life of some Activity, Fragment or in more general terms "task" is that the data will keep memory occupied even if the user is never coming back to your app. The app process is kept alive until Android decides it needs the memory. That time between your last legit use of the bitmap and Android finally killing your app and thereby cleaning the memory can be seen as leak.
If we had magic powers, we could simply clean up the cache once we know that is going to happen. There are some realistic options though:
Using Android's callbacks: understanding onTrimMemory( int level )
time limits on references: e.g. https://github.com/jhalterman/expiringmap
2) is not an option. If you're trying to use WeakReference as cache, you haven't understood what that class is intended for and I honestly don't understand why it is even mentioned in the documentation (weakly referenced objects should be garbage collected as fast as possible once nobody has a strong reference anymore).
SoftReference is intended for "caching" but using it as actual cache is not only broken on Android. It's broken by design because you give the garbage collector the responsibility to maintain a cache for you without telling it how to prioritize objects or how much memory it should keep guaranteed under what conditions. The result is that the GC will clean up the wrong thing or simply everything. SoftReference can be used to in addition to a proper cache that knows how to clean up.
In addition to all of that: be aware that a single Bitmap may not be enough. If you had a look at Tasks and Back Stack you may have noticed that 1 app process can have 2 or more independent tasks in parallel. That means there could be whatever Activity uses the bitmap in different stages. If you don't want to overwrite your cache bitmap between those all the time, you may have to have 1 bitmap per task.
I don't know how to do it per task, but you can easily use a retained fragment to tie the life of your bitmap to that of an activity (ignoring screen rotation etc): http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html / example with bitmap cache https://github.com/google/iosched/blob/master/android/src/main/java/com/google/samples/apps/iosched/util/BitmapCache.java
I think best way is to create Singleton with hard reference plus some methods for recycling and loading, I've created a lot different way Bitmap and graphics loaders and this is probably most efficient and easiest for access way
public class BitmapLoader{
public static BitmapLoader bl;
private static Bitmap b=null;
public static BitmapLoader getInstance(){
if(bl==null)
bl = new BitmapLoader();
return bl;
}
public Bitmap getBitmap(Context c){
if(b==null && c!=null)
b=loadBitmapUsingContectIfNeededOrWhateverYouWant(c);
return b;
}
public void recycleBitmap(){ //for e.g. onDestroy() Activity or other
if(b!=null)
b.recycle();
}
}
keeping loaded Bitmap in LruCache is also good idea

Understanding Android App RAM Usage

My app uses a service which I start in the main activity's onCreate() method. When I first launch the app on my tablet, and view what's running in Settings/Apps/Running, it shows my service running and consuming 11MB of RAM.
Now, if I cycle the activity's life cycle 20 times by rotating the device, and go back into Settings/Apps/Running, it shows that I'm now using 29MB of RAM.
At first I thought this must be due to a memory leaks, but after taking heap dumps before and after cycling the activity's life cycle, I don't appear to be leaking any objects. Below is a screenshot from MAT, where the column titled Objects #0 lists instances of my objects before cycling, and column titled Objects #1 lists instances of my objects after cycling.
and for all objects
There don't appear to be any obvious memory leaks, and yet I can't understand why the RAM usage in Settings/Apps/Running increases after each orientation/lifecycle. Am I missing something here? Why is my RAM usage apparently increasing, when I don't appear to have any memory leaks?
Update
The reason my app was consuming more RAM on each orientation change was the result of creating custom fonts from assets. I had created a custom TypefacedTextView (can be seen as an object in the screenshots above) that appears to have been reloading the fonts into memory each time the view was created. Removing the TypefacedTextViews has fixed the problem. The problem was made clearly apparent using the adb tool with command shell dumpsys meminfo my.package.com which listed my abundant font Asset Allocations.
There's a short blog post which, I believe, holds a lot of information nonetheless. You can find it here.
In it you find an intereseting explanation of what can/will happen if you manage your Activity's references wrongly:
private static Drawable sBackground;
#Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this);
label.setText("Leaks are bad");
if (sBackground == null) {
sBackground = getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);
setContentView(label);
}
This code is very fast and also very wrong; it leaks the first
activity created upon the first screen orientation change. When a
Drawable is attached to a view, the view is set as a callback on the
drawable. In the code snippet above, this means the drawable has a
reference to the TextView which itself has a reference to the activity
(the Context) which in turns has references to pretty much anything
(depending on your code.)
Since you're talking about memory leaks on orientation changes, you may very well be making the mistakes the author details in his post.

Java android optimization. Non-static or static method?

I have a static class with a method in it that I run a few hundred times. Currently, everytime the method is run, it creates two different stack objects. If I were to make that class non-static so I can create the two stacks on construction and then reuse them by clearing them, would it be quicker? I guess the answer depends on creating a new stack object vs clearing an existing one (which is likely empty anyway) and if the performance gain (if any) from clearing it instead is greater than the performance loss from having a non-static method.
I've tried profiling the two and it never seems to work, but that's a different question.
It depends on how you use static variables and method in your code.
Instance variables and objects are stored on the heap.
Local variables are stored on the stack.
Static variables are stored in a permanent area on heap. The garbage collector works by marking and sweeping objects. Static variables cannot be elected for garbage collection while the class is loaded. They can be collected when the respective class loader (that was responsible for loading this class) is itself collected for garbage.
If i have a value to be passed to another activity i would use intents instead of static variables.
In a custom list adapter we use a static viewholder. So using static variables or methods depends on different situation.
You can analyze memory usage by objects using a tool called MAT Analyzer. The video in the below talks about memory management and how to detect and solve memory leaks
http://www.youtube.com/watch?v=_CruQY55HOk.
MemoryInfo mi = new MemoryInfo();// current memory usage
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
activityManager.getMemoryInfo(mi);
long availableMegs = mi.availMem / 1048576L;
http://developer.android.com/training/articles/perf-tips.html. Have a look at this link for performance tips especially the topic under Prefer Static Over Virtual.
Memory availabilty is one of the criteria's to be considered using static variables and methods for performance and avoiding memory leaks.
This is really a question about trying to reuse objects. You can reuse objects in a static method too if you declare a static member. Separately: yes it's probably better to design this without static anything.
In any event, the upside to reuse is avoiding object creation. You still pay some cost of "clearing" the object's state. Or else, you risk memory leaks in the case of something like a Stack.
There is an ongoing maintenance issue: you add new state to the object, and, did you remember to update the method that clears it?
You also need to now synchronize access to this method or otherwise prevent two threads from using it at once. That could introduce a bottleneck as threads can't execute the method concurrently.
You also always pay the memory cost of this object living in memory for the entire runtime.
In the olden days, people would create object pool abstractions to avoid recreating objects. This has its own complexity and runtime overhead, and are generally well out of favor, since the cost of creating an object and GCing it is so relatively small now.
Trying to reuse objects solely for performance is rarely a performance win. It would have to be in a tight loop and not suffer from several possible problems above to be worth it.

does android.media.SoundPool cause memory leak?

I found these code may case memory leak on android 2.1
SoundPool soundPool = new SoundPool(10, 7, 0);
...
...
soundPool = null;
every time after the execution, the MAT pluging tells that two String objects of "android:unnamed_thread" are added to the heap of the process. is that an issue?
did you try to run soundPool.release() instead of soundPool = null?
I see two possibilities (there may well be more).
The first (most likely) is true of all Java objects: just because you set the reference to null doesn't automatically mean that the object behind it will be garbage-collected.
If a SoundPool object itself contains a reference to the two thread objects, none of the three will necessarily be GC'ed until space is required (although that depends, of course, on how aggressive your collector is).
The second (less likely) is that Android may be smart enough to cache thread (or even SoundPool) objects in case they need to be used again. They may nave done this as a performance optimisation if object creation is more expensive than object re-cycling.
In that case, they would still have a reference to the objects somewhere in a cache and they wouldn't be considered eligible for garbage collection.

Categories

Resources