DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Using Heap Dumps to Find Memory Leaks
  • Understanding Root Causes of Out of Memory (OOM) Issues in Java Containers
  • All You Need To Know About Garbage Collection in Java
  • Difference Between InitialRAMPercentage, MinRAMPercentage, MaxRAMPercentage

Trending

  • From Zero to Production: Best Practices for Scaling LLMs in the Enterprise
  • Performing and Managing Incremental Backups Using pg_basebackup in PostgreSQL 17
  • Integration Isn’t a Task — It’s an Architectural Discipline
  • Beyond ChatGPT, AI Reasoning 2.0: Engineering AI Models With Human-Like Reasoning
  1. DZone
  2. Coding
  3. Java
  4. Memory Leak Due to Time-Taking finalize() Method

Memory Leak Due to Time-Taking finalize() Method

All objects in Java implicitly inherit from java.lang.Object. This class contains multiple methods, which can be overridden in the child class.

By 
Ram Lakshmanan user avatar
Ram Lakshmanan
DZone Core CORE ·
May. 15, 25 · Tutorial
Likes (0)
Comment
Save
Tweet
Share
2.8K Views

Join the DZone community and get the full member experience.

Join For Free

All objects in Java implicitly inherit from java.lang.Object. This class contains multiple methods, which can be overridden in the child class. 

One such overridable method is finalize(). Before objects get garbage collected from memory, the JVM will execute the finalize(). So, if you need to close any resources that were opened in the class (like backend connections, Files…), it can be done in this method. 

However, this method has a few shortcomings; when it’s not carefully handled, it will result in an OutOfMemoryError. This post explains those in detail and how to address them.

Note: The finalize() method has been deprecated in Java 9 due to several inherent flaws (one of them is exposed in this post). So, refrain from using the finalize() method in your code, instead, refer to the solutions given in the ‘What are the alternatives to finalize() methods?’ section of this post.

Poorly Implemented finalize() Method Results in OutOfMemoryError

Here is a sample program that simulates OutOfMemoryError due to the improper implementation of the finalize() method:

Java
 
01: public class TimeTakingFinalizer { 
02:     
03:    static class SlowFinalizerObject { 
04:        
05:        private String largeString = generateLargeString();         
06: 
07:        @Override 
08:        protected void finalize() throws Throwable { 
09:            
10:            Thread.sleep(5000); // Simulating slow finalization 
11:        } 
12:    } 
13: 
14:    public static void main(String[] args) { 
15:        
16:        int count = 0; 
17:        
18:        while (true) { 
19:                             
20:            new SlowFinalizerObject(); // Creating objects rapidly 
21: 
22:            if (++count % 10 == 0) { 
23:                System.out.println("Created " + count + " objects."); 
24:            } 
25:        } 
26:    } 
27:    
28:    private static String generateLargeString() { 
29:        
30:        StringBuilder sb = new StringBuilder(5 * 1024 * 1024); // ~5MB 
31:        while (sb.length() < 5 * 1024 * 1024) { 
32:            sb.append("X"); 
33:        } 
34:        return sb.toString(); 
35:    } 
36:}


Before continuing to read, please take a moment to review the above program closely. In line #3, SlowFinalizerObject is declared. Whenever this object is instantiated, in line# 5, a huge string ‘XXXXXXXXXXXXXXXXX…’ is created and assigned to the largeString instance variable. In line #8, the finalize() method is implemented for this object. This method puts the thread to sleep for 5 seconds, to simulate a situation where this method takes a long time to complete. In line #20, SlowFinalizerObject is continuously created because of the while(true) condition in line #18. 

In a nutshell, this program is continuously creating SlowFinalizerObject and the finalize() method of this object takes 5 seconds to complete. When this program is executed, it will result in java.lang.OutOfMemoryError: Java heap space. However, if the finalize() method is removed (i.e., line #8 – #11), this program can run continuously fine without any OutOfMemoryError.

Why Does the Slow finalize() Method Result in OutOfMemoryError?

To find the answer to this question, we need to understand how the JVM executes the finalize() method:

  1. Whenever an object is eligible for garbage collection, and if it implements the finalize() method, it will be added to an internal queue which is present in java.lang.Finalizer class.
  2. For the entire JVM, there is one single Finalizer thread, that will execute the finalize() method of all the objects that are present in the internal queue. 
  3. Say if the finalize() method takes a long time to complete (as in this case), the Finalizer thread will get stuck, and the internal queue will start to build up quickly.
  4. When the queue starts to grow beyond the allocated memory size, an OutOfMemoryError will be thrown.

How to Diagnose the finalize() Method Created by Memory Leak?

You want to follow the steps highlighted in this post to diagnose the OutOfMemoryError: Java Heap Space. In a nutshell, you need to do:

1. Capture Heap Dump

You need to capture a heap dump from the application, right before the JVM throws an OutOfMemoryError. 

In this post, 8 options to capture the heap dump are discussed. You might choose the option that fits your needs. My favorite option is to pass the -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<FILE_PATH_LOCATION> JVM arguments to your application at the time of startup.

Example:

Java
 
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/tmp/heapdump.hprof


When you pass the above arguments, the JVM will generate a heap dump and write it to /opt/tmp/heapdump.hprof file whenever an OutOfMemoryError is thrown.

2. Analyze Heap Dump

Once a heap dump is captured, you need to analyze the dump. In the next section, we will discuss how to do heap dump analysis.

Heap Dump Analysis – finalize() Method

Heap dumps can be analyzed using various tools, such as HeapHero, JHat, and JVisualVM. Let’s analyze the heap dump captured from this program using the HeapHero tool.

Fig: HeapHero flags memory leak using ML algorithm


The HeapHero tool uses machine learning algorithms internally to detect whether any memory leak patterns are occurring in the heap dump. Above is the screenshot from the heap dump analysis report, flagging a major warning that java.lang.ref.Finalizer class is occupying 95.61% of the overall memory. It’s a strong indication that the application is suffering from a memory leak, and it originates from the java.lang.ref.Finalizer class.

Largest Objects section highlights java.lang.reg.Finalizer

Fig: Largest Objects section highlights java.lang.reg.Finalizer


The ‘Largest Objects’ section in the HeapHero analysis report shows all the top memory-consuming objects, as shown in the above figure. You can clearly notice that the java.lang.ref.Finalizer class occupies 95.61% of memory. 

Outgoing Reference section of java.lang.reg.Finalizer

Fig: Outgoing Reference section of java.lang.reg.Finalizer


The tool also gives the capability to drill down into the object to investigate its content. When you drill down into the java.lang.ref.Finalizer class reported in the ‘Largest Object’ section, you can see all its child objects of this class. 

From the above figure, you can notice the actual string ‘XXXXXXXXXXXXXXXXXXXXXXX…’ to be reported. Basically, this is the string that was added in line #5 of the above program. Thus, the tool helps you to point out the memory-leaking object and its source, with ease.

What Are the Alternatives to finalize() Method?

There are a few strategies to close the resources instead of the finalize() method. They are:

1. Use try-with-resources

For objects holding external resources like files or streams, implement AutoCloseable and use them within a try-with-resources block. This guarantees that cleanup logic is executed promptly when the block completes, reducing the chance of lingering memory.

2. java.lang.ref.Cleaner

Cleaner is a modern, safer replacement for finalize(). It allows you to register a cleanup action that runs after an object becomes unreachable, without blocking garbage collection like finalize() can.

3. java.lang.ref.PhantomReference

With PhantomReference, you can monitor when an object is ready for collection. By using a reference queue, you can trigger cleanup code outside of the GC thread, avoiding the pitfalls of finalization delays.

4. Use Explicit Cleanup Methods

Design your API with a clear close() or dispose() method and document the need to call it. This gives developers full control over resource management and avoids the unpredictability of automatic finalization.

Conclusion

From this post, we can understand that a poorly implemented finalize() method has the potential to bring down the entire application. By leveraging alternative strategies to finalize() method and using tools like HeapHero for faster root cause analysis, you can protect your applications from hard-to-detect outages.

Java virtual machine garbage collection Memory (storage engine)

Published at DZone with permission of Ram Lakshmanan, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Using Heap Dumps to Find Memory Leaks
  • Understanding Root Causes of Out of Memory (OOM) Issues in Java Containers
  • All You Need To Know About Garbage Collection in Java
  • Difference Between InitialRAMPercentage, MinRAMPercentage, MaxRAMPercentage

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

OSZAR »