In Java, when the garbage collector fails to collect some unused objects that are still being referenced internally due to the developer’s mistake, this is called a memory leak. It becomes critical overtime; heap memory may keep growing and lead to application out of memory errors.
Causes of memory leak in Java
There are several reasons that cause the memory leak in Java; some of them are mentioned below:
1. Static fields and Objects:
In Java, static fields belong to the class rather than an instance of the class, which means they will remain in the memory as long as the application does not complete its execution. If the static file holds any object reference, then that object will not be available for the garbage collector even if it is not needed any more, and this will lead to a memory leak.
Below, we have a simple program in which we are adding elements to a list. We will see how creating a static list object will drastically change the memory consumption.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
public class Main {
private List<String> list = new ArrayList<>();
public void initialize(){
for(int i = 0; i < 10000000; i++) {
this.list.add("paulsofts");
}
System.out.println(this.list);
}
public static void main(String[] args) {
new Main().initialize();
}
}
Before running our application, we have the following VisualVM monitor feed:
Once we run our Java program, the JVM will start consuming more heap memory. We can see that earlier it was using 500 MB of heap, and once we run our program, it marks up to 1500 MB and then becomes stable once program execution is completed and drops down to 1250 MB.
Now, we will make our list as static, JVM will assign even more memory to the the list.
2. Unclosed resources (Connection, InputStream or BufferReader)
Unclosed resources contribute a lot to memory leaks. Say, for example, if we have used a buffer reader and we have not closed it. It will remain present in the memory, and that causes a memory leak. We can close connections or resources in two ways:
- Explicitly close it manually by writing the closing statement.
- Using more advanced features of Java, such as try-with-resource (introduced in JDK 1.7), will implicitly close the connections.
3. Improper handling of Objects in Java
The circular dependency between objects can lead to the memory leak. Say, two objects are there, object A and object B, and object A is referring to object B and object B is referring to object A. In this case, the garbage collector gets confused and will not be able to collect the objects.
4. Thread Pool
If pool threads are not able to release the resources after the execution, it will leads to memory leak in Java.