Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6757111
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 26, 20262026-05-26T13:36:26+00:00 2026-05-26T13:36:26+00:00

I am currently trying to diagnose a slow memory leak in my application. The

  • 0

I am currently trying to diagnose a slow memory leak in my application. The facts I have so far are as follows.

  • I have a heap dump from a 4 day run of the application.
  • This heap dump contains ~800 WeakReference objects which point to objects (all of the same type, which I will call Foo for the purposes of this question) retaining 40mb of memory.
  • Eclipse Memory Analysis Tool shows that each of the Foo objects referred to by these WeakReferences is not referred to by any other objects. My expectation is that this should make these Foo objects Weakly Reachable and thus they should be collected at the next GC.
  • Each of these Foo objects has a timestamp which shows that they were allocated over the course of the 4 day run. I also have logs during this time which confirm that Garbage Collection was happening.
  • A huge number of Foo objects are being created by my application and only a very small fraction of them are ending up in this state within the heap dump. This suggests to me that the root cause is some sort of race condition.
  • My application uses JNI to call through to a native library. The JNI code calls NewGlobalRef 4 times during start of day initialisation to get references to Java classes which it uses.

What could possibly cause these Foo classes to not be collected despite only being referenced by WeakReferences (according to Eclipse Memory Analyser Tool)?

EDIT1:

@mindas
The WeakReference I am using is equivalent to the following example code.

public class FooWeakRef extends WeakReference<Foo>
{
  public long longA;
  public long longB;
  public String stringA;

  public FooWeakRef(Foo xiObject, ReferenceQueue<Foo> xiQueue)
  {
    super(xiObject, xiQueue);
  }
}

Foo does not have a finalizer and any finalizer would not be a consideration so long as the WeakRefs have not been cleared. An object is not finalizable when it is weakly reachable. See this page for details.

@kasten The weakreferences are cleared before the object is finalizable. My heap dump shows that this has not happened.

@jarnbjo I refer to the WeakReference Javadoc:

“Suppose that the garbage collector determines at a certain point in time that an object is weakly reachable. At that time it will atomically clear all weak references to that object and all weak references to any other weakly-reachable objects from which that object is reachable through a chain of strong and soft references.”

This suggests to me that the GC should be detecting the fact that my Foo objects are “Weakly reachable” and “At that time” clearing the weak references.

EDIT 2

@j flemm – I know that 40mb doesn’t sound like much but I am worried that 40mb in 4 days means 4000mb in 100 days. All of the docs I have read suggest that objects which are weakly reachable should not hang around for several days. I am therefore interested in any other explanations about how an object could be strongly referenced without the reference showing up in a heap dump.

I am going to try allocating some large objects when some of these dangling Foo objects are present and see whether the JVM collects them. However, this test will take a couple of days to setup and complete.

EDIT 3

@jarnbjo – I understand that I have no guarantee about when the JDK will notice that an object is weakly reachable. However, I would expect that an application under heavy load for 4 days would provide enough opportunities for the GC to notice that my objects are weakly reachable. After 4 days I am strongly suspicious that the remaining weakly references objects have been leaked somehow.

EDIT 4

@j flemm – Thats really interesting! Just to clarify, are you saying that GC is happening on your app and is not clearing Soft/Weak refs? Can you give me any more details about what JVM + GC Config you are using? My app is using a memory bar at 80% of the heap to trigger GC. I was assuming that any GC of the old gen would clear Weak refs. Are you suggesting that a GC only collects Weak refs once the memory usage is above a higher threshold? Is this higher limit configurable?

EDIT 5

@j flemm – Your comment about clearing out WeakRefs before SoftRefs is consistent with the Javadoc which states:
SoftRef: “Suppose that the garbage collector determines at a certain point in time that an object is softly reachable. At that time it may choose to clear atomically all soft references to that object and all soft references to any other softly-reachable objects from which that object is reachable through a chain of strong references. At the same time or at some later time it will enqueue those newly-cleared soft references that are registered with reference queues.”

WeakRef: “Suppose that the garbage collector determines at a certain point in time that an object is weakly reachable. At that time it will atomically clear all weak references to that object and all weak references to any other weakly-reachable objects from which that object is reachable through a chain of strong and soft references. At the same time it will declare all of the formerly weakly-reachable objects to be finalizable. At the same time or at some later time it will enqueue those newly-cleared weak references that are registered with reference queues.”

For clarity, are you saying that the Garbage Collector runs when your app has more than 50% free memory and in this case it does not clear WeakRefs? Why would the GC run at all when your app has >50% free memory? I think your app is probably just generating a very low amount of garbage and when the collector runs it is clearing WeakRefs but not SoftRefs.

EDIT 6

@j flemm – The other possible explanation for your app’s behaviour is that the young gen is being collected but that your Weak and Soft refs are all in the old gen and are only cleared when the old gen is being collected. For my app I have stats showing that the old gen is being collected which should mean that WeakRefs get cleared.

EDIT 7

I am starting a bounty on this question. I am looking for any plausible explanations for how WeakRefs could fail to be cleared while GC is happening. If the answer is that this is impossible I would ideally like to be pointed at the appropriate bits of OpenJDK which show WeakRefs being cleared as soon as an object is determined to be weakly reachable and that weak reachability is resolved every time GC runs.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-26T13:36:26+00:00Added an answer on May 26, 2026 at 1:36 pm

    I have finally got round to checking the Hotspot JVM source code and found the following code.

    In referenceProcessor.cpp:

    void ReferenceProcessor::process_discovered_references(
      BoolObjectClosure*           is_alive,
      OopClosure*                  keep_alive,
      VoidClosure*                 complete_gc,
      AbstractRefProcTaskExecutor* task_executor) {
      NOT_PRODUCT(verify_ok_to_handle_reflists());
    
      assert(!enqueuing_is_done(), "If here enqueuing should not be complete");
      // Stop treating discovered references specially.
      disable_discovery();
    
      bool trace_time = PrintGCDetails && PrintReferenceGC;
      // Soft references
      {
        TraceTime tt("SoftReference", trace_time, false, gclog_or_tty);
        process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true,
                                   is_alive, keep_alive, complete_gc, task_executor);
      }
    
      update_soft_ref_master_clock();
    
      // Weak references
      {
        TraceTime tt("WeakReference", trace_time, false, gclog_or_tty);
        process_discovered_reflist(_discoveredWeakRefs, NULL, true,
                                   is_alive, keep_alive, complete_gc, task_executor);
      }
    

    The function process_discovered_reflist has the following signature:

    void
    ReferenceProcessor::process_discovered_reflist(
      DiscoveredList               refs_lists[],
      ReferencePolicy*             policy,
      bool                         clear_referent,
      BoolObjectClosure*           is_alive,
      OopClosure*                  keep_alive,
      VoidClosure*                 complete_gc,
      AbstractRefProcTaskExecutor* task_executor)
    

    This shows that WeakRefs are being unconditionally cleared by ReferenceProcessor::process_discovered_references.

    Searching the Hotspot code for process_discovered_reference shows that the CMS collector (which is what I am using) calls this method from the following call stack.

    CMSCollector::refProcessingWork
    CMSCollector::checkpointRootsFinalWork
    CMSCollector::checkpointRootsFinal
    

    This call stack looks like it is invoked every time a CMS collection is run.

    Assuming this is true, the only explanation for a long lived weakly referenced object would be either a subtle JVM bug or if the GC had not been run.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Im currently trying to filter some information from a file we have coming to
Im currently trying to downlaod a audio track from a WCF, i need some
I'm currently trying to get the most popular productID from my MSSQL Database. This
I'm currently trying to limit the memory resources of the process. Before to do
I am currently trying to get the code coverage report for a PHP application
Im currently trying to move my site from localhost on my machine to my
Currently trying to set up and deploy a Sencha Touch 2 application. I'm following
I am currently trying to create a html:select tag from an enum so it
Am currently trying to create a jQuery fading banner. However I have noticed an
Im currently trying to add the SlidingDrawer in my application.. My activity consists GridView

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.