 I am going to be talking about Eclipse memory analyzer tool. I am Lakshman from Litly Labs. We will basically cover what is memory analysis, what do we need to use the tool and then go through some definitions of what is important and relevant in terms of memory analysis and we will see a couple of small examples of very obvious memory leaks and see how they manifest in the MAT. We will just go through some basic functionality of MAT. People are expected to know basic Android app development and basic understanding of what is heap and what is garbage collection. If you have already used MAT quite well and all, you probably will not gain much from this session. You can stay back to help me answer any questions though. Now we will slip into a small commercial break. Just wanted to pitch my company. We develop a tool that helps Android developers and testers understand their application better and gives them inputs, deeper insights into their application to improve the quality of theirs. So, there is a booth set up in the floor below. You can go and check live demo of it, that is. Now on to the main program, why do you need to do memory analysis? The common reasons are you want to identify leaks and you want to reduce the memory footprint of an app. I must be joking here. Android uses Java, which is managed code, there are no leaks in here. I hope everybody understands what the kind of leaks that we are talking about in Java. These are typically when we talk about leaks in the managed code, these are not your classic style leaks where basically objects are left out without any references to them because those are easily garbage collected. Typically what we consider leaks in managed code are objects that are not useful anymore. Their purpose is done, but because of some residual code or some code holding on a reference, the garbage collector does not determine it to be garbage anymore. These are the kinds of things that you consider leaks. We will see some examples of why or how that may happen and we will try to go through and see how to identify those through that. So some of the typical problems especially with respect to Android programming are holding a context object. Context object is something that I mean you need for a lot of Android API calls, so at least I have seen quite a few people passing around and holding references to that and all. This context object typically happens to be an activity and the activity will hold the reference to all the view objects and everything down below. These typically tend to be quite big. If you keep holding and what happens is suppose the user rotates the screen, then the activity is invalidated and the new activity will be created and all. So if you were holding onto references, these do not get garbage collected if you have held a reference in a static variable and things like that. One thing is non-static inner classes. So when you have an inner class which is not declared as static, it needs to have access to its parent variables. So by default it will have a reference to its parent object. So as long as the inner object is alive, the parent will be alive and vice versa. We will see this also as an example in coming this thing. Other thing is caching of references. In one example is you would have an array or an array list stack of objects and you would keep storing things into it and when you are done with it, you would move a pointer. Let's say you have a link list or an array list or something. When you are pushing, you copy the reference into a particular index variable wherever you need and whenever you are done, you basically move the pointer because that is enough. What happens when you are done with that is for the actual collection or container object still has a reference to that. So for the garbage collector, it does not deem it to be a leak anymore. It does not deem it to be garbage. Another thing is, similarly, at least one thing people do is to optimize memory allocations which are deemed costly. People keep storing when once they are done, they try to keep a collection of objects. I ran into this recently so I can relate to my experience. I was allocating objects and I said, okay, I want to cache them so that I don't do memory allocations too much and I kept pushing them into collections. So even when its use is over, this collection will keep growing and it may actually become quite huge. These are the problems typically that may cause memory issues. Now before we go and understand MAT and try to look at it, first some basic definitions that are useful in understanding this. First one is called shallow size. Shallow size is basically the size of an object. Let's say you have an entity, it's a 4 bytes or if you have a reference, depending on whether it's a 32-bit VM or a 64-bit VM, it will be either 4 bytes or 8 bytes. If you have an object that has say 2-inch, it will be 4, 4, 4, 8 plus the reference and this kind of thing. That will be its shallow size. What is retained size is basically the size of all the objects that are kept in memory by this object. That is, let me go show an example. We take a simple object graph here. Basically, all these arrows imply that somebody is holding a reference to them. For the sake of example, let's assume all the objects from A to F are each of 100 size. If you see the size indicated in black is basically the shallow size of each object which is 100 for each of them and the colors are not showing up, but the number that is shown in the bottom is called the retained, is basically the retained size of each object. Let's start from the leaves. For these three things, it's pretty straightforward, the retained size of each object. It doesn't have any other references, so its retained size is the same as its shallow size. If you go to C, it holds a reference to D. Assuming that this is a subtree where there are no other references to any of the objects from outside, D is in memory solely because of the reference from C. C's retained size includes D. The retained size of C is now 200. If we take E and F, E has a reference to F, but E's retained size is only shown as 100. It's not shown as 200. The reason is F is not in memory just because of the reference from E. F is in memory because it has two references, both from F, B and E. That is why E's retained size is just shown as 100. B, because E and F are both controlled by E. B, I mean both have references only from B. If B is gone, E and F both can become garbage. B's retained size is 300 and A is basically some of all these, which is 600. What is a dominator? Dominator is just what we have covered, which is basically, in this case, the object that is holding, the object that is causing this, when we are talking about a particular object, let's say E here, what is the object that control, I mean that is determining why E is not a garbage. In a more graph theory way, if all the differences, if all the paths to a particular object from a garbage collector route are passing through a particular object, then that object is considered to be the dominator of the chained object. In this case, F's dominator is not E but B because all the paths to F will have to pass through B and GC routes are basically, the objects are points from where garbage collection starts. These are things like native objects and your thread stacks because whatever is being held there are not garbage. From there, basically, a garbage collector will start its mark and sweep algorithm to identify what is garbage and what is not. Whatever I have just explained, if we just go back here, this is basically how the dominator tree for the previous object graph looks like. Now let's go into an example. This demonstrates one of the things that I talked about, a non-static inner class. If you see, main activity is, I mean, regular activity and it has a non-static inner class called Lee class. What we are doing is it has a static reference to that particular Lee class and what is being done here is just allocation of one, we are making sure that we are allocating only one Lee class object. Seems harmless, everything seems fine here. Let me just bring up Eclipse. This is the code that is and I will quickly run this. Let me just first explain what happens here. Because there is a static member called static handle to this Lee object, from the class object of main activity, there will be a reference that will be held to the Lee class. Because this Lee class is not declared to be a static inner class, it will have a reference to the parent object of it whenever it is created. What happens is ultimately, even if the main activity is replaced with a new activity because of screen rotation or something, this object will keep holding on to the original activity, the old activity, the first activity on creation of which this leak is initialized will always be in memory. I wanted to demo that just by running it. I should have brought this up before. While this goes on, what we can do, I will just quickly go to the demo of heap, we will proceed and we will come back to how to create the heap dump so that we can examine it. So, what is MAT, which is basically the topic of discussion we have come to there now, is basically it is a tool to examine heap dumps. Heap dump is nothing but an image or the map of all the objects that are in the heap at any point of time. So, it has basically every details of all the objects that are present and all the references, etc. So, that lets you examine very deeply how things are, I mean how things are in the memory at any point. How do you generate a heap dump, there are multiple ways. First one is through DDMS, so in DDMS view, there is this button, small one here if you can see, which if you use, it can create a hpro file. The other option is if you know at a particular point in your code, you are running out of memory or you are getting a error at some point. If you want to create a heap dump at a precise point, what you can do is use this OS call android.os.debug.dumphpro file, you have to supply it a file name. Make sure that the file, sorry, we have not even gone into the demo. Make sure that the file is world writable, so that it can dump, otherwise you can send a signal, but that will work only in an emulator. So, as we are running out of time, let me quickly go to some demos of MAT, so with MAT you can, sorry, you can do basically lot of, you can examine every details, let me just quickly bring it up. This is the one we earlier tried, the demo of the MAT, the report of that. The most important things are dominated tree, which we have discussed, so it shows that it can show the various objects and it is their shallow and retained heap. So, whenever you want to, whenever you are running out of memory and whenever you want to find leaks, this is one of the important places where you would look. You would sort by retained heap and you can see how the things are, which are the objects are holding on to the maximum memory, right. Another view that is useful is histogram view, where it shows typically by, started by the size of various objects and it shows, again you can sort them by the shallow, I mean size of their shallow heap, retained heap. It can also show you the number of instances of various objects that are present, right, and say for instance you, and one of the other useful things is you can run a regular expression here. So, if you type main activity, it will show all the instance, I mean it will show all the classes that are matching, right. That was, that error was from my earlier dump, where I tried to dump, I guess, I assume. So, you can see list of all objects with incoming references. Here, this is an earlier dump that I am just using to demonstrate the issue. So, there are three main activity objects. I have done it like with the rotation of visor thrice and so, if we, so how do we determine whether it is appropriate or not, right. So, what you need to, what you would want to look at is path to GC roots, right, excluding weak references, great. Let me see if something else works. So, I am getting some issue with the earlier heap dump, but basically if you look at any of the objects, any particular object to determine whether there is a, what is keeping it in memory, this is what, this is the view you would want to look at, right. You would want to see something called path to GC roots excluding weak references, okay. So, that will show you what are the objects that are holding, I mean how this object is determined to be not garbage, what are the objects that are from the GC root which are what is the path of reference to this particular object, right. So, that will tell you, I mean when, if we had gotten the earlier thing working, it would have shown that there is a handle from that leak object to the main activity class, one of the instance of the main activity class. So, that is one of the, one useful this thing. And another thing just to show is, I mean I am really running out of time, I didn't, I should have planned the session better, but there are a lot of useful features that you can keep discovering. One other thing is it is very much type where you can find a lot of things about your, you can do, examine the contents of collections even if they are not just typical, regular arrays by looking at the, and you can even do, so you can do something called group by value. I am just trying to give you some of the tips, some of the things. It will, if there are multiple objects, right, if there are like hundreds of integers, integer objects, then it will show basically group them by the value of their, this value of the object. So, for instance in case of a string, if there are a lot of string objects, let me just try it quickly, right, I mean in this particular heap there are about 10,000 string objects, right, and I basically say, show group by value, it should show me, here I mean it shows that there are 9999 strings which are just all of the, all point, all have the same value, hello, right. I mean these are some of the tips that you can use to identify what is taking up in your, what is taking up memory in your program, right. You would look at number of details, I mean number of instances of various objects and try to look at, try to identify if there are duplicates, if there are, maybe you are creating, instead of copying references, maybe you are duplicating objects for instance, those kind of things. And one of the most powerful thing, one of the more, another most useful thing is something called object query language, right. Except something, it gives you some basic query language that you can run on the heap. So for instance, you can say something like select star from java.lang.string str where str.to string equals to hello and it will show, and you execute the string, okay, maybe what I am doing, sorry, maybe I should just run it. So well, I am doing something wrong, anyway, you can, you can run basically expressions on the, on each of these objects and map it and identify the, everything that matches that particular query and it will show all the instances of the particular object, of the particular class which match that, okay. So yeah, that's basically a very brief overview of MAT. Hope you can at least open it, help you to open it next time and look at it, although I haven't gone in detail about much, many of the features that I wanted to. Okay, that's done. Are you going to upload this PPT somewhere so that we can actually. Sure, sure, I will, I will do that. Yeah, thank you. Hi, this is Prakya. Sure. So prior to Honeycomb motion, so basically when we create any bitmap, the memory will be allocated in the native instead of java. Right. So is it possible to find out any leaks in the, any object or anything, bitmap showed in the native memory? Not as far as I know. So yeah, prior to Honeycomb, yeah, all your bitmaps will be in native memory and those are not visible to the heap dump. So is there any way to find out the, any memory loss or leak which is happening in the native level? So what we write in the NDK port or CSC++? Yeah, I'm not aware of it. Satu, do you have any? Excuse me. Yeah. Yeah, sorry. So I have two questions. One is the example that you gave. Yeah, the example that you gave for the leak class. Leak class was holding a reference to the activity. Yes. The leak object was holding a reference to the activity. Right. But the moment on create would be called again. Yeah. The leak object itself would be dereferenced from the activity. Yeah. I mean, the reason it is there is because it is, there is a static reference to that leak in the class. Agreed. But that's, since it's static, there will be only one instance of that. Yes, there will be only one instance. And the moment it gets dereferenced and a new leak, leak activity of course is created. So, so there are two leak activities. One activity, but the second leak activity is actually dereferenced. Okay. I mean, obviously, I, the code does not, I mean, in the code we are not, we are never creating a second leak activity. Yeah. The first leak activity ever created is being held in the static member. Yes. And that static member will always be holding reference to the activity which was part of, it was part of. Right. Right. And from the second time onwards, right, there is no other leak activity being created. Okay. Okay. So now the original leak object that was created, the first one, is held from the class because it is a static member. Yes. Right. So the first activity that was ever used, that was ever created will never go out of scoper. It will always have reference. I can just. So basically what I'm trying to understand here is that if, if, if an activity has a reference to an object and the object in turn has a reference to the activity, will both the objects remain in memory? So, so the, the mistake here is that the, the class, that the inner class is not declared a static. The reference to it is static, but the class is not static. Right. So, so what, I mean, so that is why it has a reference to its parent. If the class was declared to be static, it would not have another, that reference. What I'm asking is, if there is a cyclic inner reference, will both the objects remain in the memory? So as long, no, as long as it is not a static, there is no static reference, it would not. Right. The second question is images. So I read somewhere that images are handled very differently in Android. They are actually, the memory, while rendering the memory is actually created in native and then. So, yeah, that is what earlier person also asked. Sorry. Yeah. Basically before Honeycomb, the bitmap objects used to be stored in native memory. Right. So they would not be visible to your heap dump or you will not be able to examine them through MAT. Right. Whereas after Honeycomb versions, these objects also are allocated on the heap as a byte arrays. So you would be able to examine them. Okay. The question is actually, when I dereference the images, will the objects be garbage collected? Yeah. So we don't have to do anything extra to actually garbage collected. Sorry. Yeah. Okay.