One of the core benefits of Java is the JVM, which is an out-of-the-box memory management. Essentially, we can create objects and the Java Garbage Collector will take care of allocating and freeing up memory for us. Nevertheless, memory leaks can still occur in Java applications.
What is a Memory Leak in Java?
A scenario that occurs when objects are no longer being used by the application, but the Garbage Collector is unable to remove them from working memory – because they’re still being referenced.
A memory leak is bad because it blocks memory resources and degrades system performance over time. And if not dealt with, the application will eventually exhaust its resources, finally terminating with a fatal java.lang.OutOfMemoryError.
Symptoms of memory leak are as below:
Symptoms of memory leak are as below:
- Severe performance degradation when the application is continuously running for a long time
- OutOfMemoryError heap error in the application
- Spontaneous and strange application crashes
- The application is occasionally running out of connection objects
Types of Memory Leaks in Java
Static Field Holding On to the Object Reference
In Java, static fields have a life that usually matches the entire lifetime of the running application(unless ClassLoader becomes eligible for garbage collection).eg public static final ArrayList<Double> list = new ArrayList<Double>(1000000);
Prevention
- Minimize the use of static variables
- When using singletons, rely upon an implementation that lazily loads the object instead of eagerly loading
Through un-closed Resources and un-closed Connections
Prevention
- Always use finally block to close resources
- The code (even in the finally block) that closes the resources should not itself have any exceptions
- When using Java 7+, we can make use of try-with-resources block
Improper equals() and hashCode() Implementations
When defining new classes, a very common oversight is not writing proper overridden methods for equals() and hashCode() methods.
HashSet and HashMap use these methods in many operations, and if they’re not overridden correctly, then they can become a source for potential memory leak problems.
Calling String.intern() on Long String
The Java String pool had gone through a major change in Java 7 when it was transferred from PermGen to HeapSpace. But for applications operating on version 6 and below, we should be more attentive when working with large Strings.
If we read a huge massive String object, and call intern() on that object, then it goes to the string pool, which is located in PermGen (permanent memory) and will stay there as long as our application runs. This blocks the memory and creates a major memory leak in our application.
Prevention
- The simplest way to resolve this issue is by upgrading to latest Java version as String pool is moved to HeapSpace from Java version 7 onwards
- If working on large Strings, increase the size of the PermGen space to avoid any potential OutOfMemoryErrors
How to Find Leaking Sources in Your Application
Verbose Garbage Collection
One of the quickest ways to identify a memory leak is to enable verbose garbage collection.
By adding the -verbose:gc parameter to the JVM configuration of our application, we’re enabling a very detailed trace of GC. Summary reports are shown in default error output file, which should help you understand how your memory is being managed.
Do Profiling
The second technique is the one we’ve been using throughout this article – and that’s profiling. The most popular profiler is Visual VM – which is a good place to start moving past command-line JDK tools and into lightweight profiling.
Review Your Code
Simply put – review your code thoroughly, practice regular code reviews and make good use of static analysis tools to help you understand your code and your system.
Finally, this is more of a general good practice than a specific technique to deal with memory leaks.
No comments:
Post a Comment