Author: Bradley Kofi
In the last article, we covered the most basic aspects of what memory leaks are, what causes them and how to eliminate them from your program.
As a preamble, memory leaks happen when the garbage collector (GC) is unable to clear unreferenced objects from working memory. Considering how much of its popularity Java owes to its garbage collector, how can it this be possible? As it turns out, the GC has a few weak spots:
Unreferenced static fields: The GC is unable to clear static fields unless the class that owns it is unloaded, which only happens if the Classloader that called it is garbage collected.
Unclosed system resources: The GC indirectly frees up files since classes like FileInputStream are written such that if an instance is garbage collected, the ‘close()’ method will be called first. This way, unclosed system resources don’t always pose a risk, so a lot of developers tend to look over them.
Most systems have hard limits on how many files can be open at once, and in addition to hard-to-reproduce bugs like different processes being unable to access the file or OS errors, such issues can be quite problematic to debug. They aren’t memory leaks in the exact sense but memory usage does remain high in the time that the stream remains open.
Besides, it’s also worthwhile to remember that class unloading may or may not happen depending on the JVM implementation.
Unclosed connections: Like with unclosed resources, unclosed database or network connections can lead to significant memory use if not unloaded.
Additional reasons memory leaks may occur include having a small heap space, excessive page swapping by the operating system and long delays in garbage collection.