Home United States USA — software Debugging RAM: Detect/Fix Memory Leaks in Managed Languages – Heap Deep Dive...

Debugging RAM: Detect/Fix Memory Leaks in Managed Languages – Heap Deep Dive (Part 2)

209
0
SHARE

Java & JavaScript are garbage collected languages. But memory leaks can still plague them. Avoid, detect and fix these heap problems using this guide.
Join the DZone community and get the full member experience. In the previous installment, I talked about the Java garbage collector. In this part, I’ll discuss the most common memory issue: the memory leak. I focus on managed languages, specifically Java, but I will mention some native code tools which are interesting. A memory leak contributes to heap size, which isn’t the most pressing bug in most cases. But when left alone, memory usage can become a problem and, by that point, finding the issue is hard. Unlike a crash dump, where we get a reference to a specific line, a memory leak can remain hidden. Unfortunately, this often means that memory leaks can carry into production and even cause problems to end users. E.g. This recent story about memory leaks hobbling Apples latest M1 computers. Virtual memory effectively means operating systems can carry memory leaks for a very long time. The performance overhead will be noticeable, though. With the garbage collector, we often rely on automatic memory management to solve such memory issues. But that’s just not the case in real life. Typically, this problem is harder to solve for languages with manual memory management and those with reference counting. I’ll specifically exclude Rust in this discussion. I don’t have enough experience in it to say anything of value. It seems very interesting but has some complexities. There are powerful tools for application memory profiling, but even they often show data as byte arrays. This doesn’t bring us any closer to solving the issue. In this article, I’ll walk you through debugging memory usage. I’m assuming that you already know there’s a leak after reviewing memory usage. So the focus here is on narrowing it down. One problem with tracking heap memory is managing expectations. You would expect that a memory allocation will cause an equivalent growth in memory and freeing the memory would restore things. This isn’t always the case. Most memory leaks happen in the heap, but there are rare cases where the source of the leak can be in native code, PermGen space, etc. We should debug native issues using native memory tools. We can tune other types of memory via JVM flags. You can often detect the source of the memory leak by looking at the out-of-memory error message. The following types are common: Notice that this isn’t accurate, since a leak in native memory can deplete the Java heap and vice versa. We’ll need to check both, but it will give us a sense of where to start… There are MANY profiling tools for tracking/fixing memory leaks. It’s impossible to give a proper review for even a small segment of the available richness. I won’t go even into a fraction of what’s available. Instead, I’ll focus on two tools: VisualVM and Chrome DevTools (with a focus on Node). VisualVM lets us review the running application to get a snapshot of memory usage. Chrome DevTools is a more general-purpose debugger that includes the kitchen sink for JavaScript developers. It can connect to the running node application and debug them. I won’t be discussing: You can get VisualVM here. Once installed, you can launch VisualVM and connect it to our running application to see the process. In the image above VisualVM is monitoring itself, that’s pretty meta. You can perform manual garbage collection, which is very important to get a sense of the size of a leak. The heap graph provides you a bird’s-eye view of the amount of memory over time and the trend. If you did front-end work with Chrome, surely you ran into the « everything but the kitchen sink » debugging tools that are integrated into Chrome.

Continue reading...