Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 604
Bootstrapper Avatar asked May 22 '15 20:05

Bootstrapper


People also ask

How do you identify a memory leak?

Running out of memory is the simplest way to identify a memory leak, and it's also the most common approach to uncovering one. That's also the most inconvenient way to find a leak. You'll probably notice your system slowing down before you run out of RAM and crash your application.

Is memory leak serious?

Very dangerous. Memory leaks in the kernel level lead to serious system stability issues. Kernel memory is very limited compared to user land memory and should be handled cautiously. Memory is allocated but never freed.


2 Answers

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.
like image 184
Eyal Biran Avatar answered Oct 17 '22 06:10

Eyal Biran


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.

like image 1
Michael Burr Avatar answered Oct 17 '22 07:10

Michael Burr