Finding Memory Leaks

Kotlin is a JVM-based language that has a garbage collector, which is a daemon thread that runs on the JVM and is responsible for automatic memory management. This reclaims the memory allocated to objects that are no longer referenced by the program running inside the VM. We will discuss more about garbage collector later in the chapter.

In execution, a program creates the objects required for the computation. Here, the memory is allocated for objects in the heap region. Once the program has finished using these objects, they are no longer needed by the program and it holds no reference to the objects that it has created. An object is garbage collected when it is no longer referenced by the program. A memory leak occurs when the program holds the reference to objects when they are not being used by it. Consequently, these objects are not eligible for garbage collection. This increases the program's memory usage, causing memory leaks in the system. If the program creates many such objects, the memory allocated for the system will become full, which may cause the system to crash. So, the program that we write is responsible for releasing object references when they are no longer needed.

There are monitoring tools available that help us to understand how memory is utilized in the system. If we see any abnormal behavior in memory usage, we can fix it and redeploy the services.

We will write a program to illustrate a memory leak and use jvisualvm, which comes with the JDK and is used for analyzing memory utilization. jvisualvm is available under the {{path-to-jdk}}/bin directory.

Let's write a simple program that creates a hashmap and goes on adding key-value pairs to it, and a statement to print in the console when an element is added to the map:

@JvmStatic
fun main(args: Array<String>) {
try {
val map = HashMap<MemoryLeakDemo, String>()
while (true) {
map[MemoryLeakDemo("myKey")] = "value"
println("Element added to map")
}
} catch (e: Exception) {
e.printStackTrace()
}
}

The allocated memory for an entry in the map is no longer needed after it was added and printed in the console. While the program is running, we launch jvisualvm to monitor the memory. When jvisualvm starts up, we can see that the process that is running our code is already attached to jvisualvm and it shows the monitoring of that running program:

We can see from the preceding screenshot that the heap memory usage has already exceeded 200 MB and is growing. Once it reaches the upper limit and there is no memory left for objects to allocate, the program crashes with an OutOfMemoryError message. After crossing a certain limit before the program crashes, increasing the heap may appear to solve the problem, but eventually even that gets allocated and the program again runs out of memory. This is a clear indication that the program suffers from a memory leak problem.

There is also a sampler option in jvisualvm to indicate for what specific type of object the memory is being allocated. There is also an option to view the CPU usage, which is shown as follows:

This shows that the majority of the memory is allocated to type HashMap, which is what our program is adding to. The program still holds the reference to the allocated objects, so it can never be reclaimed by the garbage collector. We see that the running MemoryLeakDemo thread, which is the class that we wrote, constantly adds to the memory. This an example of a memory leak. The jvisualvm tool helps to analyze the memory leak.

When we are developing a large system and check to see how memory is being utilized in order to identify any memory leaks, we can use jvisualvm. If we see a memory leak in the code, we now have a chance to fix it.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset