Finalize() cleanup vs. Garbage Collector removing an object from memory - java

I was reading about the finalize() method and was curious:
What is the difference between the task of cleaning up objects ( setting them to NULL ) in finalize, and removing an object from memory?

What is the difference between the task of cleaning up objects (
setting them to NULL ) in finialize
setting to null removes ONE reference to the object.
if NO more references to an object exists, the garbage collector is allowed (not required) to remove the object
and removing an object from memory?
there is NO explicit way in java to remove (destroy, delete) an object.
The garbage collector will do it when he likes.
Especially the time from removing the last reference to remove/destroy the object is indefinite
There is NO need to set references to null in finalize method.
when the garbage collector call finalize the objects and its references will gone soon anyway.
I never wrote an own finalize method during my very long java experience.
The rare occasion in which it make sense to wrote an own finalize method appear if your object is dealing with os-resources. However, in general you use standard packages for os accesss

You don't "clean up" an object when you set it to null, you're just setting the reference to null, consider:
Object a = new Object();
Object b = a;
a = null;
System.out.println(b);
Once an object loses all references, it will be collected on the next GC pass. Finalize is a method that gets called when this happens, and you should avoid using it.
Just don't keep extra references around and let the GC do it's job.

finalize() is called by garbage collector when an object has no more references. You can override it and best practice is to use it in a try-catch-finally block to free non java resources like files. Anyway if you use it this way you should also call super.finalize() to ensure class hierarchy finalization.
This method is always for advanced use and shouldn't be used in normal production code. Free your resources in finally clauses in methods using those resources.

Related

Meaning of ReferenceQueue

I try to understand class ReferenceQueue
It is optional constructor argument for
SoftReference
and
WeakReference
Also it is mandatory argument for PhantomReference.
According information I have read I can write some thesises
a)for PhantomReference method get always returns null
b)
for Phantom references:
1. gc detect that object can be deleted from memory
2. reference to the object puted to the ReferenceQueue
when we invoke clear or link to reference from queue becaom unreachable and gc see that
3. finalize methods invokes
4. free memory
for weak/soft references:
1. gc detect that object can be deleted from memory
2. finalize methods invokes
3. free memory
4. reference to the object puted to the queue
When can I pass second argument to XXXReference constructor?
Which help I can get?
Why PhantomReference has not constructor without ReferenceQueue ?
What the reason to have ReferenceQuee which get methods returns null always?
Maybe, the following program helps a bit:
public class SimpleGCExample {
public static void main(String[] args) throws InterruptedException {
ReferenceQueue<Object> queue=new ReferenceQueue<>();
SimpleGCExample e = new SimpleGCExample();
Reference<Object> pRef=new PhantomReference<>(e, queue),
wRef=new WeakReference<>(e, queue);
e = null;
for(int count=0, collected=0; collected<2; ) {
Reference ref=queue.remove(100);
if(ref==null) {
System.gc();
count++;
}
else {
collected++;
System.out.println((ref==wRef? "weak": "phantom")
+" reference enqueued after "+count+" gc polls");
}
}
}
#Override
protected void finalize() throws Throwable {
System.out.println("finalizing the object in "+Thread.currentThread());
Thread.sleep(100);
System.out.println("done finalizing.");
}
}
On my system, it prints
weak reference enqueued after 1 gc polls
finalizing the object in Thread[Finalizer,8,system]
done finalizing.
phantom reference enqueued after 2 gc polls
or
finalizing the object in Thread[Finalizer,8,system]
weak reference enqueued after 1 gc polls
done finalizing.
phantom reference enqueued after 2 gc polls
The order of the first two messages occasionally differs due to the multi-threading. And sometimes, the phantom reference is reported to be enqueued after three polls, indicating that it took more than the specified 100 milliseconds.
The key point is
soft and weak references are cleared and enqueued before or right when starting finalization
phantom references are enqueued after finalization, assuming that the object has not leaked the finalize method, otherwise they are enqueued after the object has become unreachable again
the presence of a (non-trivial) finalize() method causes the need of at least one additional garbage collecting cycle to detect that the object is unreachable or phantom reachable again
Since more than 99% of all objects don’t need finalization, all JVM vendors are strongly encouraged to detect when finalize() has not been overridden or is “trivial”, i.e. an empty method or a sole super.finalize() call. In these cases, the finalization step should be elided. You can easily check that this optimization happens in your JVM, by removing the finalize() method in the above example. Then it prints
weak reference enqueued after 1 gc polls
phantom reference enqueued after 1 gc polls
Since both are enqueued at once and retrieved in an arbitrary order, the order of the two messages may differ. But they are always both enqueued after one gc cycle.
It’s worth noting that the fact, that phantom references are not automatically cleared, implies that it takes another garbage collection cycle until the object’s memory really can be reused, so the above example requires at least three cycles with the non-trivial finalize() method and two without. Java 9 is going to change that, clearing phantom references automatically, so in the above example it will take two cycles with finalization and one without until the memory really can be reclaimed. Well, to be precise, in this simple example the object’s memory will never be reclaimed as the program terminates before that can happen.
The code above also demonstrates one of the intended use cases of the Reference API. We can use it to detect when an object’s reachability changed within code under our full control, e.g. using a loop within the main method. In contrast, finalize() may be called by a different, unspecified thread at an arbitrary time. The example also shows that you can draw information from the reference object without needing the get() method.
Practical applications often use subclasses of the reference classes to add more information to them. This is what happens with WeakHashMap.Entry which extends WeakReference and remembers the hash code and value. The cleanup can be done within the normal map operations, not needing any thread synchronization. This would not be possible with a finalize() method, besides the fact that the map implementation can’t push a finalize() method into the class of the keys.
This is meant with the “more flexible than finalization” term.
The WeakHashMap demonstrates how the get() method can be useful. As long as the key hasn’t been collected, it will be reported as being in the map and can be retrieved when iterating over all keys or entries.
The PhantomReference.get() method has been overwritten to always return null to prevent that an application can resurrect the referent of an enqueued reference. This is a direct consequence of the “phantom references are not automatically cleared” rule. That rule itself is questionable and it’s original intention lies in the dark. While the rule is about to be changed in the next Java version, I’m afraid that get() will continue to always return null to be backwards compatible.
1) When can I pass second argument to XXXReference constructor?
You can do it whenever you like. You should do it whenever you need the references to be processed as they are being broken.
2) Which help I can get?
I don't understand this questiom
3) Why PhantomReference has not constructor without ReferenceQueue ?
The purpose of PhantomReference is to be a more flexible alternative to regular finalization. However, in order for that to work, the references must be enqueued for the finalization-replacing code to work. (A PhantomReference that was not enqueued could not be processed.)
By contrast SoftReference and WeakReference objects are often useful without being enqueued.
4) What the reason to have ReferenceQueue which get methods returns null always?
The ReferenceQueue API doesn't have a get() method, so I guess you are talking about the PhantomReference API. The reason that there is a get() method is for compatibility with the superclass. The reason that get() is defined to return null is as follows:
"In order to ensure that a reclaimable object remains so, the referent of a phantom reference may not be retrieved: The get method of a phantom reference always returns null."
(See the javadoc.)
In other words, it is done to make it impossible to "resurrect" the referent.
UPDATE
In fact, all of the Reference classes will clear the referent before enqueuing a Reference. (Actually, the GC itself does this directly.) Application code that pulls references from a ReferenceQueue cannot use the get() method to identify the (now deleted!) referent. They must do it some other way; e.g. based on the identity of the Reference object.
What distinguishes a phantom reference is that the get() method always returns null. (So the explanation in the javadoc is ... unconvincing.)

How to delete a java object from Heap?

You have one big object in java. it has got 4 or five references. you don't know all those references. At time on deletion you know only one reference and you want to delete that object completely. How to achieve that? and also if you want to know other references then to what is the best way to do that.
It is not in our hand.. You can just nullify it from your end..
Object a = new Object();
a = null; // after that, if there is no live thread which is accessing members,it will be deleted by garbage collector
You could try Finalize() or System.runFinalization() but frankly, if there are references still pointing to the object, then I think the GC will ignore your request.
It is not possible in Java.
If you have strong reference referring your object, you cannot force JVM to GC that object. It simply cannot guarantee the program will work.
If codes of all other references are in your control, consider changing them to use WeakReference or SoftReference
There are some things that are not in our hands and its better to leave it to the JRE to handle it. All we can do that we make sure that the we make them null explicitly after using them.
{
// Some block
HugeObject obj = HugeObject.getInstance();
// Use it
obj = null;
}
// end of block
Java memory handling is just built to prevent that. An object is guaranteed to live as long as a reference to this object exists. As far as I know there is no (official) way to get to know the other references to an object (and there should be no need for that).
In Java GC(Garbage collector) handles heap cleanup. If an Object has no live references to it then it will automatically be cleaned up. So you need to make sure there are no live references to the Object.
Making it null is one of the way. But it will not guarantee it's cleanup if there is some other Object pointing to the same reference. That is why writing good code involves closing all the resources after use which includes making it to null.
If you are running low on heap you can try increasing heap size or calling System.gc() but again calling gc manually does not guarantee gc will actually be performed. it depends on lot of parameters which are JVM dependent.
What kind of references are these to the object? Are these references created by you and at runtime you don't keep track of of those references. If this is the case, you can wrap your references to the object in soft/ weak reference and then explicitly run the GC request. Otherwise, on runtime, if any live thread has access to the object. GC shall not delete that object.
It is hard to answer no knowing your use case, but if there is one location that you want to be able to remove it from then you can store every other reference to it as a WeakReference. Java normally uses strong refrences when referencing objects and the GC will only clear something when it has no more strong references. However, if you use WeakRefrences and your strong refrence ever goes out of scope there is no guarantee that your data will remain even if it is still needed.
I could be mistaken about this though, as I haven't used this class in a year or two.
On WeakReferences:
http://docs.oracle.com/javase/7/docs/api/java/lang/ref/WeakReference.html
You can declare your objects as WeakReference and add them in ReferenceQueue. In this way , whenever your object will not be further referenced , it will be liable for GC.
/**
Initialize the reference queue , even if you don't do it , no problem . Default reference queue will be taken.
**/
ReferenceQueue<? super Object> testReferenceQueue = new ReferenceQueue<Object>();
Map<String,String> demoHashMap = new HashMap<String,String>();
demoHashMap.put("SomeValue","testValue");
// Declare the object as weak object and put it in reference queue
WeakReference<?> weakObject = new WeakReference<Object>(demoHashMap,testReferenceQueue );
demoHashMap.clear();
demoHashMap = null; // This object is not referenced from anywhere
if(weakObject!=null){
System.out.println("Object is not GCd yet");
}else{
System.out.println("It is already garbage collected");
}

Is manual object deletion possible in Java?

In some languages like Python, there are ways by we can "delete" an object from the heap explicitly. As for example:
s = "This is a Test"
del s
Now, the object s cannot be used anymore. Now, my question is, can we do anything similar in Java? Yes, I know it is garbage collected, and that is a huge advantage in most situations, but what if I want to manually delete an object? By the way, does del in Python actually delete the object, or does it delete the reference variable? Thanks in advance for any help!
can we do anything similar in Java?
No.
At most you can nullify the object:
s = null;
This will mark the object for garbage collection, and when trying to use it (except when assigning a new value to it), you will get a NullPointerException.
s = null;
...
s.foo(); //this will throw a NullPointerException
in java for sure we cannot delete the object...but we can try with System.gc(); or if we want to lost the reference of a object we can set the value of object reference null; .. but after setting null value we can't access the object but it still remains in memory......
In general you need to null all references to the object after which the object cannot be used anymore and will be deleted on next GC. But string constants objects like "This is a Test" are stored in a pool and are not deleted if even there is no reference to them.
The object will get deleted from heap once it goes out of scope. You can enclose s in the minimal possible scope where it is used. i.e. either enclose within a block of {} braces, or define a separate method where it is used
As Luiggi Mendoza has said you can not manually delete.How ever you can refer it to NULL.
To free the memory you can call System.gc() .But there is no guarantee that memory will be freed.
Before removing an object from memory Garbage collection thread invokes finalize () method of that object and gives an opportunity to perform any sort of cleanup required.

On Java garbage collection, clarification needed

Upon new A(), we allocate sufficient amount of memory to hold all object that A contains.
Object A() may contain other objects like B() and C()
Question 1: When A() is no longer needed and you want to remove it from the heap, will setting it's reference to null do the trick? (If not, what would be the right way to signal the JVM to GC this object now?)
Question 2: If so, what happens with the instances pointing to B() and C()
Question 3: Is there a way this effect can be observed? (memory being deallocated to free up the object)
Setting A to null will mark A as a candidate to be freed by the GC. Instances of B and C will be marked too if the only references to those instances were from instance A.
Edit about question 3: A simple way to debug this effect is using the method finalize; When an object is GC´ed, his finalize is called .
However, be careful with this method: finalize is not guaranteed to be executed always (as the GC is not guaranteed to free an object) and should never be used for application´s general purposes.
There are better debugging tools depending on your IDE. For example, in eclipse: http://www.yourkit.com/docs/80/help/garbage_collection.jsp
If you have live reference to B and C then it won't GCed
at any point if any object doesn't have live reference to it, that object is ready to be GCed
class A{
B b = new B();
C c = new C();
}
now when you do
A a = new A();
a= null;//instance referred by a,b & c are ready to be collected in this system
Object A() may contain other objects like B() and C()
Objects only contain primitives and refrences to other objects.
Question 1: When A() is no longer needed and you want to remove it from the heap, will setting it's reference to null do the trick?
It is rarely needed but you can do this.
Question 2: If so, what happens with the instances pointing to B() and C()
Nothing, they are unrelated objects.
Question 3: Is there a way this effect can be observed? (memory being deallocated to free up the object)
You can override the finalize() method or use ReferenceQueues. This only informs you about collected object rather than discard objects. Its best to avoid needing to do this.
Objects which do not have a strong reference from root context e.g. thread stacks, can be collected. It doesn't matter how this happens. Setting a reference to null can allow this to happen, but more often allowing a variable to go out of scope is a simpler way to discard an object(s).
If you have Object B and it points to C which points to B and there are no other references to these objects, they will still be cleaned up even though there are references to those objects.
You cannot force GC to delete an object. GC will automatically delete any objects that are safe to be deleted. You can force GC to run by invoking System.gc(), which will delete any objects it can.
A = null will delete the object only if no other references to that object exists.
In general GC exists so you don't have to worry about deletion and memory collection. If a thing is safe to be deleted, it eventually will be.
B() and C() will be deleted if A stops pointing to them and A was the only thing pointing to them in the first place.
If you set it to null, then yes it is a signal to the GC to deallocate the memory when it needs the memory. But this will only happen if there are no more instances referencing that object.
If there are still instances referencing an object, it will not be GC-ed until there are completely NO instances referencing that object. So B() and C() will be GC-ed only if A() was the only one referencing them.
This effect can be easily observed by using Java to read a huge text file (about 3mb) with a Scanner, then closing and discarding the Scanner, and invoking System.gc() when you are done.
If you nullify all the references to A and if there are no other live references to B and C then those will be GCed too when the GC runs.
Invoking System.gc() does not guarantee that gc will run instantly. It may or may not run, there is no guarantee at all.
And There is no guaranteed way to force gc run immediately as you request it.
Yes, you can see the effect as gc runs freeing memory.
to see visual graphs/info ... about heap/memory usage, you can use jdk tools, find it for windows at:
JAVA_HOME\bin\jconsole.exe
Its a thumb of rule, that when an object has NO reference attached to it, its a toast for the Garbage collector to eat.
Marking A null will, make A a toast for the GC. If the reference pointing to A, was the only reference to B and C, then both of these are too the candidate for being Garbage Collected
finalize is the object class method, that is called when an object is Garbage Collected.

Does variable = null set it for garbage collection

Help me settle a dispute with a coworker:
Does setting a variable or collection to null in Java aid in garbage collection and reducing memory usage? If I have a long running program and each function may be iteratively called (potentially thousands of times): Does setting all the variables in it to null before returning a value to the parent function help reduce heap size/memory usage?
That's old performance lore. It was true back in 1.0 days, but the compiler and the JVM have been improved to eliminate the need (if ever there was one). This excellent IBM article gets into the details if you're interested: Java theory and practice: Garbage collection and performance
From the article:
There is one case where the use of explicit nulling is not only helpful, but virtually required, and that is where a reference to an object is scoped more broadly than it is used or considered valid by the program's specification. This includes cases such as using a static or instance field to store a reference to a temporary buffer, rather than a local variable, or using an array to store references that may remain reachable by the runtime but not by the implied semantics of the program.
Translation: "explicitly null" persistent objects that are no longer needed. (If you want. "Virtually required" too strong a statement?)
The Java VM Spec
12.6.1 Implementing Finalization
Every object can be characterized by two attributes: it may be reachable, finalizer-reachable, or unreachable, and it may also be unfinalized, finalizable, or finalized.
A reachable object is any object that can be accessed in any potential continuing computation from any live thread. Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. For example, a compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner.
Discussion
Another example of this occurs if the values in an object's fields are stored in registers. The program may then access the registers instead of the object, and never access the object again. This would imply that the object is garbage.
The object is reachable if it can be involved in any potential continuing computation. So if your code refers to a local variable, and nothing else refers to it, then you might cause the object to be collected by setting it to null. This would either give a null pointer exception, or change the behaviour of your program, or if it does neither you didn't need the variable in the first place.
If you are nulling out a field or an array element, then that can possibly make sense for some applications, and it will cause the memory to be reclaimed faster. Once case is creating a large array to replace an existing array referenced by a field in a class - if the field in nulled before the replacement is created, then it may relieve pressure on the memory.
Another interesting feature of Java is that scope doesn't appear in class files, so scope is not relevant to reachability; these two methods create the same bytecode, and hence the VM does not see the scope of the created object at all:
static void withBlock () {
int x = 1;
{
Object a = new Object();
}
System.out.println(x+1);
}
static void withoutBlock () {
int x = 1;
Object a = new Object();
System.out.println(x+1);
}
Not necessarily. An object becomes eligible for garbage collection when there are no live threads anymore that hold a reference to the object.
Local variables go out of scope when the method returns and it makes no sense at all to set local variables to null - the variables disappear anyway, and if there's nothing else that holds a reference the objects that the variables referred to, then those objects become eligible for garbage collection.
The key is not to look at just variables, but look at the objects that those variables refer to, and find out where those objects are referenced by your program.
It is useless on local variables, but it can be useful/needed to clear up instance variables that are not required anymore (e.g. post-initialization).
(Yeah yeah, I know how to apply the Builder pattern...)
That could only make some sense in some scenario like this:
public void myHeavyMethod() {
List hugeList = loadHugeListOfStuff(); // lots of memory used
ResultX res = processHugeList(hugeList); // compute some result or summary
// hugeList = null; // we are done with hugeList
...
// do a lot of other things that takes a LOT of time (seconds?)
// and which do not require hugeList
...
}
Here it could make some benefit to uncomment the hugeList = null line, I guess.
But it would certainly make more sense to rewrite the method (perhaps refactoring into two,
or specifying an inner scope).
Setting an object reference to null only makes it eligible for garbage collection.
It does not necessarily free up the memory,which depends on when the garbage collector runs(which depends on JVM).
When the garbage collector runs,it frees up the heap by deleting only the objects which are eligible for garbage collection.
It is a good to have. When you set objects to null, there is a possibility that the object can be garbage collected faster, in the immediate GC cycle. But there is no guaranteed mechanism to make an object garbage collected at a given time.

Categories

Resources