What happens if I override finalize() and give reference to an object. Will that object ever be garbage collected? What is the other way to clean that object from the memory?
From the Javadoc:
The finalize method may take any action, including making this object available again to other threads.
However:
The finalize method is never invoked more than once by a Java virtual machine for any given object.
Finalize() is designed to be called by the garbage collector to remove de-referenced objects, if an object is re-referenced before Finalize() is called then you have simple prevented the GC from destroying it as it now has references again it is safe, that is assuming it was not taken during the period it was de-referenced, which could cause problems.
Remember that finalize is only called once by the JVM, so subsequence GCs will just run without giving another chance to reassign references, save objects, whatever. Potentially could cause a memory leak.
Related
Quotes from SCJP 6 study guide:
In the finalize() method you could write code that passes a reference
to the object in question back to another object, effectively uneligiblizing the object for garbage collection. If at some point later on this same object becomes eligible for garbage collection again, the garbage collector can still process this object and delete it. The garbage collector, however, will remember that, for this object, finalize() already ran, and it will not run finalize() again
Why is it designed so? The purpose of the finalize() method still holds good even when the object is marked of collection second time. Then why Java decides to skip call to finalize()?
I don't know if its the original reason, but the current implementation enqueues Finalizer instances (internal subclass of Reference) for objects overriding the finalize method with an internal ReferenceQueue that gets polled by a dedicated FinalizerThread.
And because the JVM has no way of knowing whether the object would need to be finalized a second time it cannot decide whether it would have to enqueue a new Finalizer once the finalize() method has been called.
Anyway, you should avoid using finalize(). It makes object allocation more costly, prevents escape analysis and is not a very reliable way of managing native resources because the GC can postpone the finalization for an unbounded amount of time.
Objects with an enabled finalizer are ineligible for collection; the GC only examines them after determining all the other objects which are ineligible for collection, however, and makes note of all the objects which would have been eligible for collection but for the existence of the enabled finalizer, and runs the finalize methods of such objects as soon as practical. Finalizable objects won't become eligible for collection until the finalizer has run, but the GC will have no way of distinguishing objects which become eligible for finalization as soon as the finalizer finishes, or those which were rendered ineligible for finalization as a result of actions by some object's finalizer and became eligible for collection at some later time.
The .NET Framework includes methods called IIRC GC.SuppressFinalize and GC.ReRegisterForFinalization which make it possible for code which knows an object's finalizer won't do anything useful to tell the GC not to bother calling it, and allows for code which knows a finalizer ran "too soon" to request that it run again later. The JVM, however, does not include such a feature. Since having all finalizable objects automatically reregistered for finalization once the finalizer runs would prevent them from ever getting collected, and since there's no way to manually reregister them, the net consequence is that there's no usable pattern via which an object's finalizer can be run more than once.
On the other hand, it is possible to achieve a similar effect by defining a nested class object which is finalizable, having the outer class object hold a reference to a nested-class instance, and having that nested class instance's "finalize" method chain back to cleanup code in its owner. If that cleanup code discards the nested-class instance and replaces it with a new one, then that new instance will trigger its finalizer (chaining back to its owner) on the next GC cycle where the owner is found to be unreferenced.
I wanted to understand the below statement in bold. What does it means? (Link)
An object which overrides finalize() must now be determined to be
garbage in at least two separate garbage collection cycles in order to
be collected. When the first cycle determines that it is garbage, it
becomes eligible for finalization. Because of the (slim, but
unfortunately real) possibility that the object was "resurrected"
during finalization, the garbage collector has to run again before the
object can actually be removed. And because finalization might not
have happened in a timely fashion, an arbitrary number of garbage
collection cycles might have happened while the object was waiting for
finalization. This can mean serious delays in actually cleaning up
garbage objects, and is why you can get OutOfMemoryErrors even when
most of the heap is garbage.
What phantomreference solves
With PhantomReference, this situation is impossible -- when a PhantomReference
is enqueued, there is absolutely no way to get a pointer to the now-dead object (which is good, because it isn't in memory any longer).
Because PhantomReference cannot be used to resurrect an object, the object can
be instantly cleaned up during the first garbage collection cycle in which it is found to be phantomly reachable.
Please help me understand the problem & the solution
Thanks
Contrary to popular belief, finalize methods are not triggered when their associated objects are garbage-collected, but rather when their associated objects would have been garbage-collected but for the existence of their non-default finalize methods. Objects cannot actually be garbage-collected until the system can be 100% certain that no reference to them will ever exist, but the act of running a finalize method creates a strong rooted reference to the object in question which will exist at least until the method exits. If during the execution of finalize a reference to the object gets stored elsewhere, that reference could continue to exist indefinitely. Consequently, no object whose finalized method is going to be called, nor any other object to which such an object holds a direct or indirect strong reference, can be collected until after the finalize method has run and the next GC cycle confirms that no reference to the object exists anymore.
The PhantomReference class serves to encapsulate a different paradigm: rather than keeping an object alive so the system can notify it that it's been abandoned and the only reason it's still alive is so it can receive notification of abandonment, objects requiring cleanup should create helper objects to process notification of their abandonment. If the helper objects avoid keeping references to any outside objects they don't "own", their existence won't interfere with the collection of their parent object, or other objects to which the parents hold direct or indirect references. The helper objects generally won't hold enough information to let them "do much", but that's good because they shouldn't have to do much. Instead, their design should be focused on performing the cleanup that will be required if their parent is abandoned.
ArrayList<Object> foo;
Object[] bar;
typical finalizers will do
foo = null;
bar = null;
My question, will ArrayList call a finalizer wich sets any pointers it holds to null, or do I have to step through the list an do
for(i=1; i<foo.size(); i++) foo.set(i,null); ???
And the other question: for an array, do I need to set any of its contents to null, like
for(i=1; i<bar.length; i++) bar[i] = null;
or is it enough that the whole memory block is discarded and any pointer in it out of scope afterwards?
Sorry, if the question is stupid.
After reading through the answers I figured out, that there is nothing to implement there on your own.
Some sources suggest that if something like this (memory eating apps) happens, that this is by bad design.
My core question is: Doing often
struct = new LargeStructure();
does this exaust memory?
Or does this only need the memory of one of this structures?
BTW: The problem occours in a webapp running tomcat, and there is only one session active wich holds the described pointer as a session variable.
All objects will be eligible for GC by Garbage collector automatically when they are no longer referenced. You don't have to worry about it. If you are setting the array reference to null , then the array object itself is eligible for GC if there are no other live reference to the array object, the elements of the array will be eligible for GC if there are no live references to them anymore.
As per the documentation:
protected void finalize() throws Throwable
Called by the garbage collector on an object when garbage collection determines that there are no more references to the object. A subclass overrides the finalize method to dispose of system resources or to perform other cleanup.
The finalize() method will be called after the GC detects that the object is no longer reachable, and before it actually reclaims the memory used by the object. If the object never becomes unreachable, or the GC doesn't run then finalize() may never be called.
You can try to force the JVM to call finalize() by calling System.runFinalization():
Runs the finalization methods of any objects pending finalization.
Calling this method suggests that the Java Virtual Machine expend effort toward running the finalize methods of objects that have been found to be discarded but whose finalize methods have not yet been run. When control returns from the method call, the Java Virtual Machine has made a best effort to complete all outstanding finalizations.
Theoretically finalizers let you perform last minute tasks on object before they are reclaimed by garbage collection. In practice however there is no guarantee that they will be called, so they are not very useful.
You don't have to set your object's references to null in finalizer block. Finalizer's are tipically used for last chance resource closing, it isn't a good practice, but finalizers can provide you a safety net for resource management.
My question, will ArrayList call a finalizer wich sets any pointers it holds to null, or do I have to step through the list an do
ArrayList will not call a finalizer, a finalizer thread will do that, but you don't have to worry about that. Also, you do not have to go over a list and finalize your elements your self. Java Garbage Collector will figure that one out for you and pick those objects up as long as they are not referenced anywhere else in the code.
And the other question: for an array, do I need to set any of its contents to null, like
No, same as above. Important thing to remember is that you have no reference to any value in the array, or to the array itself if you want it to be picked up by garbage collector.
I have a question on SoftReferences WeakReferences in Java.
What i know is:
GC uses algorithms to decide whether or not to reclaim a softly reachable object, but always reclaims a weakly reachable object.
Does that mean GC never runs the finalize() method on WeakReferences?
Thanks
As per The Truth About Garbage Collection
If a class defines a finalizer, then any instance of that class must
have the finalizer called prior to deallocation. This means that
deallocation is delayed by the inclusion of a finalizer.
Based on this my understanding is, irrespective of Week/Soft, if finalize defined, it will be called.
I don't follow your line of reasoning, but the finalizer is definitely always called. As soon as an object becomes finalizable, all soft/weak references to it will be cleared. So the refs can be observed as null before finalization.
How can I delete object manually in Java? Is there any method like obj.delete() or obj.kill()
There is no real way. Java has a special Garbage Collector which does that for you. Once your object doesn't have any references to it, it will be picked up by the Garbage Collector at some point and destroyed.
From Learning Java Tutorials:
The Garbage Collector
An object is eligible for garbage
collection when there are no more
references to that object. References
that are held in a variable are
usually dropped when the variable goes
out of scope. Or, you can explicitly
drop an object reference by setting
the variable to the special value
null. Remember that a program can have
multiple references to the same
object; all references to an object
must be dropped before the object is
eligible for garbage collection.
There is no way to delete an object. Java's Garbage Collector will do it automatically when an object has no more references.
You can however run the Garbage Collector once you have removed all references to an object by calling System.gc(). Please do read the method's documentation carefully. It only guarantees best-effort to delete all objects marked for deletion.
You should also go through these discussions
Java memory management best practices
Java finalize method call
One of the main reasons for Java being so popular is the Garbage Collection. You do not have to worry about allocating or deallocating memory. That being said if you want to get rid of an object just set all references to the object to null and once the garbage collector runs the object will be disposed of.
You do have to worry about closing resources such as files, sockets, database connections etc... and for that you should do it in a try/finally block.
just assign the null value to it.
Let GC take care of this
obj = null;