Java Finalizers, what tasks are really necessary - java

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.

Related

Java - Do object references get destroyed when the creating class is closed?

Say i have a class, which loads a file and then calls another method to do something to that file. For example, counting the words in the file.
Within class CountWords, a number of objects/collections are created in order to get the number of words. The method runs, the number of words is found, and then this is returned to the calling class.
My question is, do all the objects/collection created in the CountWords class get "destroyed" when control is returned to the calling class or do they remain in the memory? If the latter, would i have to set each object to null before exiting the class to mark them for collection?
We don't generally control exactly when a Java object gets destroyed. It will get destroyed some time after it becomes inaccessible - in other words, when there are no further references to it in any scope.
If you create an object, and store a reference to it in a field of another object, then the object you created continues to be accessible for as long as the object that has the reference to it is accessible.
If you have code like this
public void run() {
Foo a = new Foo();
System.out.println("This method is finished");
}
then the Foo that you created will be inaccessible as soon as run finishes, because there are no more variables with references to it. Foo will be destroyed some time afterwards. Unless of course, the constructor of Foo does some magic to register itself in some nasty static data store somewhere.
So in general, you don't need to go round setting references to null to destroy objects. From the point of view of the garbage collector, letting those references go out of scope is just as good as setting them to null.
Java is a programming language that has memory management aka garbage collection. The basic answer is, the garbage collector will take care of reclaiming the memory of unused objects.
But since you have tagged the question with [garbage-collection], you should already know this. So it’s not clear what additional detail you want to know or why you think your scenario is special in any way, to deserve an additional answer beyond “there is a garbage collector”.
You question is full of phrases that are wrong or misguiding.
“do object references get destroyed”—the storage of objects is reclaimed, there is no such thing as “destruction of references”
“when the creating class is closed”—there is no such thing as “closing of classes”
“do all the objects/collection created in the CountWords class get ‘destroyed’ when control is returned to the calling class or do they remain in the memory?”—in this form, not simple to answer
there is no such thing as “destruction”. The whole purpose of garbage collection is to permit the reuse of the memory. This implies recording somewhere that the memory is free. But the memory itself does not need to be touched.
when your method returns, these objects are eligible for garbage collection. The garbage collection itself does not have to run immediately. It may happen when there is need for free memory or when the CPU load is low.
As said, even if the garbage collector ran, the result is that the memory is now considered to be free, not necessarily to “scrub” the memory. So the objects may “remain in the memory” until actually being overwritten by other objects. So that’s simply the wrong question. You actually want to know whether the memory will be reusable.
“If the latter, would i have to set each object to null before exiting the class to mark them for collection?”—“the latter” still implies that the memory is free, semantically. But what do you want to “set to null”? The references do not exist anymore. The objects are unreachable.
The answer is there is nothing you can do and there is nothing you should do. That’s the whole point of garbage collection, no need for you to do anything.
We don't need to set the objects to null after coming out the function . For this Java have garbage Collector , which runs on the Java Virtual Machine which gets rid of objects which are not being used by a Java application anymore. It is a form of automatic memory management.
For example :
for (int i =0 ; i<10 ; i++) {
String s = String.valueOf(i)
}
In the above code, the integer s is being created on each iteration of the for loop. This means that in every iteration, a little bit of memory is being allocated to make a integer object.
Going back to the code, we can see that once a single iteration is executed, in the next iteration, the integer object that was created in the previous iteration is not being used anymore -- that object is now considered "garbage".
Eventually, we'll start getting a lot of garbage, and memory will be used for objects which aren't being used anymore. If this keeps going on, eventually the Java Virtual Machine will run out of space to make new objects.
That's where the garbage collector steps in.
The garbage collector will look for objects which aren't being used anymore, and gets rid of them, freeing up the memory so other new objects can use that piece of memory.
Automatic memory management schemes like garbage collection makes it so the programmer does not have to worry so much about memory management issues, so he or she can focus more on developing the applications they need to develop.

Why is finalize() only called once by garbage collector?

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.

Importance of phantomreference in java

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.

overriding finalize(), referencing object inside it

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.

Can objects destroy themselves? (Java)

We all know that the JRE will destroy any object that can no longer be referenced. But is there a way for an object to explicitly destroy itself? Or is that forbidden to avoid the dangling pointer problem?
Naively, I would like to say this = null, but that is disallowed by the compiler (this is probably not a true variable anyway).
Conversely, is there a way for an object to forcibly keep itself alive, by maintaining private copies of this, or otherwise?
No. In fact, you cannot forcibly destroy anything. Even if you have no references to an object, it will continue to exist in memory until the garbage collector decides to run and collect it.
You could keep an object alive by keeping a static reference to it.
Ignoring the academic aspect, you can't ensure an object is physically destroyed in Java (or most any other garbage collected language, like C#). This is because destroying objects is expensive (partly because of the memory compression phase), so the point is to run it as few times as possible.
This said however, you can force an object to release its allocated resources using the disposable pattern, where the object in question exposes a public method to release resources, and you can call it at any time (or it gets called automatically in the finalizer). It requires a bit more bookkeeping, but it gets the job done if really needed.
No you can't destroy an object.
What you could do is have a wrapper object that holds the actual object. If you make sure that nobody else has a reference to that object removing the reference (e.g. by setting it to null) will make the object qualify for the garbage collector. Note that it is still up to the GC to decide when and if to actually collect the garbage.
In order to keep an object alive you need to make sure that there is a reference to it. One way would be to have a static reference from the class of the object. As long as nobody unloads the class your object will stay in memory.
As you said I think it is forbidden to avoid dangling pointer problems. Java memory model is based on Stack and Heap model, if an object destroys itself then what would go to stack (or) other pointers, which references the object?

Categories

Resources