Java and Memory Leaks
OverviewThe term "memory leak" is used in Java in a manner which is different to how it is used in other languages. What does a "memory leak" mean in general terminology and how is it used in Java?
A memory leak, in computer science (or leakage, in this context), occurs when a computer program consumes memory but is unable to release it back to the operating system.The JVM reserves the heap as virtual memory on startup and doesn't gives that memory back until it exits. This virtual memory turns into main memory as it is used. This is why the virtual size and the resident size for a JVM can be very different and the resident memory can grow without the virtual memory changing.
In object-oriented programming, a memory leak happens when an object is stored in memory but cannot be accessed by the running code.
The GC can always find every object on the heap, even those which are not reachable to the application. As such there is no object which is not reachable to running code.
however, many people refer to any unwanted increase in memory usage as a memory leak, though this is not strictly accurate from a technical perspective.
In Java, the amount of memory required cannot be determined without a full GC. It is normal to see the "used" memory of a Java application sawtooth. Returning to the same amount of memory used after each GC indicates the memory required has not increased.
A memory leak can diminish the performance of the computer by reducing the amount of available memory. Eventually, in the worst case, too much of the available memory may become allocated and all or part of the system or device stops working correctly, the application fails, or the system slows down unacceptably due to thrashing.
This is how the term is used in Java. There is a reduction in available memory, conclusion: it is a memory leak.
But is it really a memory leak?
Examples of "memory leaks" in JavaRecently, two questions were asked on StackOverflow which illustrate a variety of views over what a "memory leak" means in Java.
Is Go subject to the same subtle memory-leaks that Java is?
Creating a memory leak in Java
In the first article there was a view expressed that a "memory leak" is when an application holds references to objects which are no longer needed. Another view was that the JVM itself doesn't have memory leaks.
In the second article there were many examples of how the JVM could be used to hide away memory usage or operations which would consume memory. Examples included File.deleteOnExit(), creating large static fields, discarded sockets, file handles, threads, JDBC connection which you don't need.
The File.deleteOnExit on exit must use some memory to be able to perform its task. This is not a leak in my option as it is not retaining memory which is not needed.
Having static fields and threads which you don't need will waste memory and this is bug which the JVM cannot correct for.
However, creating sockets, file handles, and JDBC connections the JVM does handle. When the finalize() method is called, these resources are cleaned up.
Diagnosing excess memory consumptionIf you have a system which is getting an OutOfMemoryError, you can add -XX:+HeapDumpOnOutOfMemoryError to generate a heap dump you can analyse with a free profiler like VisualVM, jhat or a commercial profiler like YourKit.
If you want to analyse a running system, you can use jmap which can give you a break down of the biggest consuming classes or a full heap dump.
ConclusionIn Java it is meaningful to refer to objects which are retained and are not longer needed as a "memory leak".
There is nothing in the Java language which is prone to this problem and the JRE libraries do protect themselves from bugs in application code.
Your application can still have a memory leak, and you need to make sensible choices about when you still need a resource, in particular a thread and if you hold onto it too long it can mean you have a "memory leak".