Memory, Memory, Memory…
Memory is a critical part of Java, in particular, the management of memory. As a developer, memory management is not something you want to be doing on a regular basis, nor is it something you want to do manually. One of the great benefits of Java is its ability to take care of the memory model for you. When objects aren’t in use, Java helps you out by doing the clean up.
But that’s also where the problems begin. With Java, maybe your app isn’t using an object anymore, but if you don’t tell the virtual machine that you’re not using it anymore it doesn’t clean it up. This is a memory leak. We’ve all seen them. Objects start building up in your heap and your app comes grinding to a halt.
Memory leaks typically happen as a result of improper programming – usually its a case where the developer didn’t relieve all references to an object. Similar objects in Java, as you know, are put together into collections or maps, so the problem can get compounded if you don’t remove particular data sets from collection. The more that goes into collection, the more space you lose.
When Java manages the memory model for you, or rather the creation/destroying of objects that are unused, it puts them in a heap. This heap is always of a certain size and has a maximum of available space. If memory management is done poorly, you will run out of that space for the heap. Collections add up and then the JVM crashes.
Traditionally, there have been two primary methods for diagnosing memory leaks – heap dumps and profilers.
The first, a heap dump, basically allows you to see which object is holding a reference to the collections. It gives you a good idea of what objects are causing the problem, but it doesn’t tell you who is accessing the collection and who’s not. It tells you where the collection is, but not the characteristics of who’s using it. Heap dumps are also usually quite large, in gigabytes, and a big heap dump is tedious to review. It takes a lot of resources to analyze and open a heap dump, then read it and identify the issue.
The second method, a combination of a heap dump and a profiler, gets you a little bit closer, but not much. Memory profilers try to help you analyze your heap dump. They have live data and now you know who is creating the objects, but you still don’t what’s actually causing the leak.
Let’s say I have an employee object. The employee object gets put in collection and the profiler will tell you who created it. What the profiler doesn’t tell you is who put it in and who removes it from the collection. Profilers tell you the birth of the object, rather than cause of the leak. By all means, this helps you narrow it down, but you need solid knowledge of the application for a profiler to really help you identify the cause, and then it still takes significant time and resources to find your leak.
We hear this from a lot of people. Many companies try these tools, but every couple of days their app crashes. So what do they do? They restart the JVM or CLR. Their apps crash again, and again, they restart. The application management is a nightmare because they have no way to find or fix their memory leaks.
Both heap dumps and profilers can be helpful in development and pre-production, but once your apps are out in the wild, profilers just aren’t useable. Profilers introduce a huge amount of overhead and heap dumps pretty much stop all processing for apps in production. You basically need to take the application on that JVM/CLR offline in able to get anything done.
These tedious processes are getting harder and harder to maintain as today’s applications advance. Heaps are getting bigger as applications get more complex, and eventually, these methods just don’t cut it.
AppDynamics & Memory Leaks
Our approach to date has been to provide comprehensive transaction snapshots, particularly obvious code problems that can give you some insight into where the issue might be. To effectively isolate and address memory leaks, transaction and code path analysis is critical.
That brings us to some interesting developments from AppDynamics. With the release of AppDynamics 3.0 today, we’ve given companies a way to directly identify the root cause of their memory leak. We can automatically detect the leak, identify who’s creating it, as well as which code path or business transaction is causing it. You can read more about it here.
The benefit of this? Less downtime and reduced MTTR. We’re pretty excited. Hope you are, too.