Memory Leaks in Java – Part 1

Memory leaks in Java - photo of a pipe join with a leak spouting water.

Background

The Java Virtual Machine(JVM) provides a runtime environment for our Java code. The JVM has two primary functions:

  • It allows Java programs to run on any device in a platform independent manner. It does this by converting the compiled Java bytecodes into native machine code.
  • It manages and optimizes program memory.

The JVM memory manager creates different memory pools at runtime. The most important pools are the stack and the heap.

  • The stack is used for temporary storage of local variables and parameters. These are small data types such as primitives and object reference data types.
  • The heap is used to store actual object instances, which can be of any size.

Memory Leaks

In every programming language, memory is a vital and scarce resource. So we, as programmers, must manage memory with care. We need to be thoughtful about the allocation and deallocation of memory. If we don’t manage memory properly, it can result in memory leaks.

As a Java application runs, it creates objects on the heap. When the objects are no longer in use, the garbage collector removes them from the heap. This then frees memory preventing leaks.

The garbage collector cannot remove objects if other objects still reference them.

A memory leak occurs when a program unintentionally refers to object that it no longer needs. This is usually due to logical coding errors. These object references stop the garbage collector from disposing of the objects.

As a result, the application consumes more and more resources as it runs. This eventually leads to a fatal OutOfMemoryError.

To refresh your memory about garbage collection, see the blog post on garbage collection.

Symptoms of Memory Leaks

Memory leaks are bad! They can block file resources, reduce memory availability and degrade system performance.

How do we know if our application has any memory leaks? At first, our application will run as fast as expected, but its performance will start to slow down over time. It should work well on small data sets. As the size of the data sets increase, we will experience performance issues.

If we watch the JVM memory usage, we’ll see an ever-increasing usage of old/perm-generation memory in the JVM. After that, we’ll get unexpected crashes with fatal OutOfMemoryError heap errors.

Causes of Memory Leaks

Many different coding issues can cause memory leaks. Let’s look at three:

  • The use of large static fields.
  • Incorrect or missing equals() and hashCode() implementations.
  • Unclosed file resources.

The lifetime of static variables is usually the same as the lifetime of the running application. They live as long as the program runs unless we explicitly set them to null. Forgetting to do this can cause memory leaks.

Incorrect equals() and hashCode() implementations can cause memory leaks. A common problem is if we put objects that are missing their hashCode() or equals() methods into a hash table. Memory leaks can occur when we put duplicate objects into the hash table. The table will keep on growing as we add duplicate objects. With correct hashCode() and equals() methods, the table will reject these duplicates.

If we forget to close file resources after we use them, the application will run out of open file handles. It will then start consuming more memory. We should use the try-with-resources statement when working with files. This will ensure that any opened resources are automatically closed.

Other common causes for memory leaks are:

  • The creation of very large objects.
  • The use of anonymous classes.
  • The use of finalizers.
  • Lots of large session objects in a web application.
  • Insertion without deletion into Collection objects. This happens when we forget to remove objects from the collection even though we don’t need them any more. The garbage collector can’t remove these objects, because they’re still being referenced.
  • Unbounded caches.
  • Listener methods that aren’t invoked.

Detecting and Fixing Memory Leaks

Detecting memory leaks can be difficult. During development we can use static code analysers. These tools can check for potential leaks. They can’t catch all the issues because we only get memory leaks while the application is running.

To find memory leaks, we can use a variety of runtime tools to help identify the source of the leak. Once we’ve found the code causing the leak, only then we can fix it. Three common detection techniques are:

  • Using profilers.
  • Enabling verbose JVM garbage collection messages.
  • Analysing heap dumps.

Profilers watch Java bytecode constructs and operations at the JVM level. This includes object creation, iterative executions, method executions, thread executions, and garbage collections.

Java profilers give us a comprehensive set of data we can use to trace our coding mistakes. Profilers help us find memory leaks, thread problems and performance slowdowns. Profiling tools give us a fine-grained analysis of every problem, and an idea of how to solve them. Running a profiler and acting on the results can lead to a more stable and scalable application.

Conclusion

In the next few posts, we’ll look at some of the causes of memory leaks and their solutions in more detail. We’ll look at some of the tools we can use to identify leaks.

Please share your thoughts, questions and comments.

Stay safe and keep learning!

Leave a Comment

Your email address will not be published. Required fields are marked *

Code like a Java Guru!

Thank You

We're Excited!

Thank you for completing the form. We're excited that you have chosen to contact us about training. We will process the information as soon as we can, and we will do our best to contact you within 1 working day. (Please note that our offices are closed over weekends and public holidays.)

Don't Worry

Our privacy policy ensures your data is safe: Incus Data does not sell or otherwise distribute email addresses. We will not divulge your personal information to anyone unless specifically authorised by you.

If you need any further information, please contact us on tel: (27) 12-666-2020 or email info@incusdata.com

How can we help you?

Let us contact you about your training requirements. Just fill in a few details, and we’ll get right back to you.

Your Java tip is on its way!

Check that incusdata.com is an approved sender, so that your Java tips don’t land up in the spam folder.

Our privacy policy means your data is safe. You can unsubscribe from these tips at any time.