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.
Related
I'd like to use a WeakReference as a more efficient finalize() method, for the purpose of freeing native resources associated with an object as soon as it becomes possible to do so, without using finalization (which has significantly higher costs than using a WeakReference).
Since this is the only purpose of the WeakReference (I will never use the WeakReference to obtain the referenced object), it seems wasteful to take the time and space to maintain a list of my WeakReferences to prevent them from being garbage collected.
But if a normal object is constructed and no strong reference is kept to it, it will simply be freed by the garbage collector, and I can't find anything in the Javadoc that suggests this is different for a WeakReference.
Is it necessary to keep a reference to a WeakReference to prevent it from being garbage collected, or, if it's to be enqueued in a ReferenceQueue, will that keep it alive until it's been collected from the queue?
Is it necessary to keep a reference to a WeakReference to prevent it from being garbage collected
Have a look at the java.lang.ref package description, it dedicates a whole paragraph to answering your question:
The relationship between a registered reference object and its queue is one-sided. That is, a queue does not keep track of the references that are registered with it. If a registered reference becomes unreachable itself, then it will never be enqueued. It is the responsibility of the program using reference objects to ensure that the objects remain reachable for as long as the program is interested in their referents.
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.
Garbage collection identify the objects that are no longer referred to by any variable and then reclaims the memory occupied by the objects.
I don't whether this process is done in a regular interval or as soon as an objects reference count falling down to zero.
suppose, if GC works immediately whenever an objects reference count falling down to zero then there is no need for requesting GC by calling System.GC();So, what is purpose of this method in this case?
GC is neither done in a regular interval nor as soon as an objects reference count falling down to zero (Note: that most JVM implementations do not use a reference counting algorithm, so this last point is moot).
When GC will run is decided by The garbage collection algorithm.
When you call System.gc(), you say to the garbage collector to make a clean-up. The problem is that it isn't clear when the GC will respond to your request. Even more, it is possible that GC to not run at all when you call it. In java you cannot predict how the GC will work. (That's why is considered bad practice to put your cleanup code in Object's finalize() method). In Java, the out of reference objects are collected for garbage automatically. That's why you don't need to call System.gc(). In special cases, when you want run it if possible, you can try to make use of this method, but the behavior is not guaranteed. (as specified above).
Most modern JVMs use a "stop-the-world" garbage collector, that is a garbage collector that stops all the application threads in the program, performs the garbage collection, and then resumes the application threads. This means that before doing the garbage collection, all threads in the application should reach a point that is safe to stop the thread.
An Object becomes eligible for Garbage collection or GC if its not reachable from any live threads or any static refrences in other words you can say that an object becomes eligible for garbage collection if its all references are null. Cyclic dependencies are not counted as reference so if Object A has reference of object B and object B has reference of Object A and they don't have any other live reference then both Objects A and B will be eligible for Garbage collection.
Generally an object becomes eligible for garbage collection in Java on following cases:
1) All references of that object explicitly set to null e.g. object = null
2) Object is created inside a block and reference goes out scope once control exit that block.
3) Parent object set to null, if an object holds reference of another object and when you set container object's reference null, child or contained object automatically becomes eligible for garbage collection.
4) If an object has only live references via WeakHashMap it will be eligible for garbage collection.
There are methods like System.gc () and Runtime.gc () which is used to send request of Garbage collection to JVM but it’s not guaranteed that garbage collection will happen.
There are two answers:
It is not specified by the JVM spec, the JLS or any of the other definitive Java documents when the garbage collector will run. It is therefore implementation specific.
In practice, a couple of different strategies are commonly used. For a non-concurrent collector, the GC is triggered when an attempted allocation fails because there isn't enough unallocated space. For a concurrent collector, a collection is started when the amount of free space falls below a pre-determined threshold. (For HotSpot concurrent GC's, the threshold ratio is a tunable parameter.)
No modern Java GC uses reference counts.
The purpose of the System.gc() is to allow an application to give the JVM a hint that "now would be a good time to run the garbage collector". The JVM is allowed to ignore that hint. As a general rule, triggering the GC that way is inefficient in terms of CPU usage. The only legitimate reason to do it in production code is as a way to avoid GC pauses in a highly interactive application. (You try to force a GC at a point when you know that interactivity is not required; e.g. between "levels" in a game.)