Finalized is holding lot of memory 2.5 gig out of 4 g
Asked Answered
M

2

7

I have read many articles how finalizer works. Here is my understanding: If a class have finalize method implemented Jvm would create an instance of Finalizer as a watch dog on that object.

When GC runs it would mark object to be disposed and add them into the reference queue then finalizer thread would pick those objects from the queue and execute their finalize method.

My question is: How do I find the object from the heap dump whose finalize method wasn't completed for some reason and started piling up the reference queue?

Is reference queue in a specific order?

Murther answered 28/7, 2016 at 11:54 Comment(7)
Just wondering: what are your finalizer methods doing? Why do you have so many objects that want to use a method, that at least in theory, nobody should rely on?Wiegand
It seems from the source code, that ReferenceQueue works like a List - it contains Reference objects, each Reference refers to the next Reference. Maybe the first object is what you needs. Maybe you should try to add aspect on finalize method and add some logging (like call Finalize for xxx; Finalize completed) - the last entry in the row will point to the object which was started to finalize, but finalize wasn't completed.Glochidium
I would probably go the other way and perform a text search for classes that have non-trivial implementations of finalize() - are there too many candidates in your codebase?Juggle
@Juggle GC doesn't run finalizers. See java.lang.ref.Reference class and nested ReferenceHandler class. GC only adds references to static field pending. All other job is doing in java code in Reference Handler and Finalizer threadsReprieve
@Reprieve fair point. Removed incorrect comment. I guess I mixed that up because I had just read the wording from finalize: "Called by the garbage collector on an object when garbage collection determines that there are no more references to the object."Juggle
@Reprieve The wordong of the language specification JLS 12.6 is different (or at least less specific): "The particular definition of finalize that can be invoked for an object is called the finalizer of that object. Before the storage for an object is reclaimed by the garbage collector, the Java Virtual Machine will invoke the finalizer of that object."Juggle
Anyway, the most important sentence from the JLS might be: "The Java programming language does not specify how soon a finalizer will be invoked, except to say that it will happen before the storage for the object is reused." - As long as nothing attempts to reclaim the memory, there is no guarantee that an Object will ever be finalized.Juggle
W
0

This might not be the answer you are looking for, but have you considered using PhantomReference instead of overriding finalize()? Here is an article that talks about it.

The basic idea is that it is not recommended to rely on finalyze() method for the pre-mortem cleanup because

  • You can't predict when it will be called.
  • It takes up resources from the JVM.
  • It can prevent objects from being garbage collected.

PhantomReference provides a cleaner way to trigger an action upon object's removal by garbage collector.

Object objectToHandle = new Object();
ReferenceQueue queue = new ReferenceQueue();
PhantomReference reference = new PhantomReference(objectToHandle, queue);

When objectToHandle will be removed from memory by garbage collector, its reference will be added to the queue. You can detect this by calling queue.remove() and perform your clean-up action then.

// will block until a reference becomes available
Reference removedRef = queue.remove();
//.. you can now perform clean-up actions

Note: PhantomReference.get() always returns null, so it is impossible to bring back the object after it has already been removed from memory.

Whoopee answered 28/7, 2016 at 13:7 Comment(0)
R
0

Yes, you can get object from heap dump.

First, finalizer ref will be removed from queue in java.lang.ref.Finalizer.FinalizerThread#run, then in runFinalizer it will be removed from doubly-linked list of unfinalized refs in method remove.

But you can find this ref, because you know it GC root ( it exists on FinalizerThread's stack)

How to find it in eclipse MAT:

  1. Go to histogram and filter by class java.lang.ref.Finalizer
  2. right-click on row with finalizers -> Merge shortest paths to gc roots with all refs.
  3. Expand row with FinalizerThread ( normally it should contain one object java.lang.Finalizer )
  4. Click on that expanded row, and in inspector panel you can click on attributes tab, finalized object will be a referent enter image description here
Reprieve answered 28/7, 2016 at 16:36 Comment(2)
Thanks for the reply. I'm not seeing option for inspector panel. How do I open inspector panel.Murther
Never mind. Thank you so much for your help. I was able to find the option.Murther

© 2022 - 2024 — McMap. All rights reserved.