On Java garbage collection, clarification needed - java

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.

Related

How to not reference an Object when it is not used so it gets deleted by GarbageCollection

I have an array list that will constantly have different amounts of items in it.
It won't be deleted when it's empty.
Can this cause memory leaks?
I see people saying to make something eligible for garbage collection you have to de-reference it. What does this mean?
An empty array is not a memory leak risk.
Memory leaks happen when a collection accepts unlimited references. It's hard to see how an empty list will be a problem.
An object that has a reference to an empty list will keep it in memory.
The garbage collector will mark an object as eligible for garbage collection when no other object refers to it. All references to that object have to be removed.
You can set reference to null to "de-reference" object. Like this for example:
Object o = new Object();
o = null;
In java when nothing points to the object (there is no reference to the object) then the object is "eligible" for garbage collector.
When it comes to memory leaks it really depends on your situation but it is possible to have some leaks due to not de-referencing.
Developers sometimes talk about "memory leaks" in Java. What they mean is that they have a lot of memory allocated that they no longer require, but in principle the application could reference if it wanted to. This is different from the "classical memory leak" which you would see in a language like 'C' where the application explicitly has to allocate an deallocate memory. As this question is about Java I won't concern myself with the "Classical Memory Leak", but just understand that the two are different
As #hdw3 correctly states, in Java an object is eligible for garbage collection if you have no reference to it. This is a specific case of a more general rule - an object is eligible for garbage collection if it can not be referenced in any way by your application. There is a subtle but important difference here...
Case 1
If you have a reference to object 'A' and that object has a reference to object 'B'. (This could be your ArrayList if contains a single item.) Neither object is eligible for garbage collection as the String can be referenced through the list.
As soon as you loose the referenced to your first object then neither object is accessible from your application, so both become eligible for garbage collection.
Case 2
Imagine you have a reference to object 'A' and that object has a reference to object 'B', AND object 'B' has a reference back to object 'A'. Objects 'A' and 'B' are both accessible so neither are not eligible for garbage collection.
As soon as you loose your reference to object 'A' then 'B' also becomes inaccessible. Both objects become eligible for garbage collection, even though they reference each other.
You can loose your reference to the object in a couple of different of ways.
The usual way is to simply exit a method that has the only reference to the object.
As #hdw3 points out reassign your reference so that it points to something
Something called "SoftReferences" exist, but you only need to worry about them if you are implementing large caches.
What you'll find is that in Java the Garbage Collector almost always does the right thing for you and you don't need to bother about memory too much.
The Java "Memory Leak" I mentioned earlier occurs if you've got a large structure you application no longer requires, but in theory the application could reference objects in that structure. For example you've got a massive List of Strings, you've finished processing them but haven't existed the method yet. This is when you'd assign your reference to null, to make ALL objects in the structure eligible for garbage collection

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

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.

What will GC do if there is a two level soft referenced object

I know in Java we have concept of soft reference. What if:
1) There is a soft reference "sf" refer to an object A
2) In object A, it has a strong reference refers to object B
3) object A & B are not referenced anywhere else.
By definition, object A and object B are both "softly reachable", right?
Then say we are running out of memory now, GC kicks in. Is it possible that GC will recycle object B but not object A?
If that's the case, later if we want to access object B through "sf", it will be null. How java avoid such case to happen?
I don't see any explain in java doc.
Then say we are running out of memory now, GC kicks in. Is it possible that GC will recycle object B but not object A?
No. The GC will not break strong references in reachable objects. (It will, of course break references in unreachable objects as part of the reclamation process. But you can't observe that happening ... because to observe it, you'd need the object to still be reachable.)
This is a consequence of this statement in the javadoc for the java.lang.ref package.
"Finally, an object is unreachable, and therefore eligible for reclamation, when it is not reachable in any of the above ways."
... where "the above ways" includes strong, soft, weak and phantom reachability.
The two highlighted words mean that eligibility for reclamation is a consequence of being in the unreachable state. Since none of the other states mention reclamation eligibility, we conclude that non-reachability is a precondition for reclamation.
This certainly aligns with common sense. If (hypothetically) the GC was allowed to "null out" strong references in reachable objects, it would be impossible for an application to safely work with objects after they had gotten into this state. (Consider the case where the nulled-out reference was in an instance of a library class ...)
I think a short introduction on how tracing GCs basically work should clear things up.
A tracing GC (the ones used in Java and .NET all fall into that category) has a set of so called root pointers, those are global variables (in java that means static variables of classes) and all live variables in the stackframes. The GC traverses these and marks all objects that are alive, i.e. reachable through references from at least one of the root pointers. When it has finished, all live variables have been marked and the rest can be garbage collected.
A soft reference now can be handled in two different ways: a) we follow the soft reference and mark all objects in it or b) we don't. What exactly happens is at the mercy of the given JVM implementation, but after that has been decided there's no other difference.
Hence there are two possible scenarios:
The GC follows the soft reference to A in which case none of the two objects will be GCed.
The GC doesn't follow the soft reference to A (and there are no hard references to it). A is GCed, B is GCed if no live object has a reference to it.
From the docs:
"An object is softly reachable if it is not strongly reachable but can be reached by traversing a soft reference."
"An object is strongly reachable if it can be reached by some thread without traversing any reference objects"
I think thats pretty clear. B is softly reachable because it is only reachable by traversing a soft reference.
Said Docs

Interview Question on Java finalize method

I have came across difficult (for me) Java interview question on finalize method. Suppose you have given finalize method as shown below:
public void finalize()
{
a.b = this;
}
Now the following object scenario is given.
How would you solve this problem? If A was not referring to B then this problem could be easier as GC will run, it will collect B and call finalize for B but here A is referring B so its difficult. How finalize will work in this scenario?
Any ideas? Thanks in advance
The easiest way to think of Java finalization is to consider it an extra 'bit' of state that every object with a finalizer has. When a new object is created, this isFinalized bit is set to false. When the garbage collector finds that an object with a finalizer is unreachable, it checks this isFinalized bit and only reclaims the object if it is true -- if it is false it instead runs the finalizer and sets the bit to true. Once set, there's no way for the bit to ever be cleared, so in any later time the garbage collector runs, if it's unreachable, it will be collected.
Very interesting question. From the JDK1.6 Doc, I find these two sentences:
1. The finalize method may take any action, including making this object available again to other threads
2. The finalize method is never invoked more than once by a Java virtual machine for any given object.
So in my opinion, for the first time, when B is collecting by GC, finalize method will be invoked if A is still available to some threads then B becomes available again, this time the GC will not collect B. But because finalize method will be invoked only once, so next time when the GC find B can't be accessed by any thread then GC will collect B.
It is not entirely clear what you are asking.
However, the JLS 12.6.2 states that the order in which objects are finalized is not specified. This means that the finalize methods for all finalizable classes should be designed to work when invoked in any order.
Note that this applies equally to unreachable and finalizer-reachable objects. In other words, the 3 objects in your diagram could be finalized in any order.
... how B will be garbage collected as A is reachable and how finalize will get called for B?
Perhaps it is a trick question. If A is reachable, then B is also reachable, so it won't be garbage collected, and its finalize method won't be called. If A becomes unreachable then so does B, and both will be finalized.
What that finalize method will actually do depends on what class it belongs to. Lets assume it is a method of the "guaranteed reachable object", and the a variable contains a reference to A:
The finalize method won't be called by the GC because the object is reachable.
Some other code could explicitly call that finalize method. If that happened, then a.b will no longer refer to B, and B will be unreachable and eligible for eventual garbage collection, finalization and (ultimately) deletion.
Sorry if I am wrong. But to me, B is a field of A, so A definitely need to keep a reference to B, and while A "always-live" object holding a reference to A, both A and B will not be GC and the problem to GC B is just not making any sense.

In Java, can you link the garbage collection between two classes?

Suppose you have an instance a of Class A. Is it possible to create an instance b of class B, such that when a is garbage collected b will be garbage collected?
I know can cheat and create a reference to a in b, so a has to wait for b or something. What I want is for instance b to be deleted when a would naturally be deleted.
No. You can never force any object to be garbage collected. That's rather the point of garbage collection.
However, if the only reference to b is from a, then it is very likely that when the collector collects a, it will also collect b.
But to be honest, if you're worrying about when objects will be collected, the chances are you've doing it wrong. There should be no difference between dead and deleted objects as far as your program is concerned. Do you have a specific use for this that you would like to discuss?
As you might know, we cannot force GC to work according to our wish.
But the first thought which can to mind was if A contains the instance of B, then naturally when a is GCed, b will be, too. This is just one scenario which came to my mind. I don't how you actually want to do it.
You can also use weak references.
Usually, you can't even be sure when a object is collected (even System.gc() does not ensure that all unreferenced objects are collected) it is up to the garbage collection algorithm to decide if an unreferenced object is collected.
There are several GC strategies (you can set it when starting the JVM), your only option is to chose one that is exhaustive so it ensures that all unreferenced objects are collected(*). Then you'll have to be sure that both a and b get unreferenced at the same time (and that the gc is not called in between -I do not know of any way to ensure that-).
(*) Don't know if such algorithm does even exist. But if it does I am pretty sure it will have a heavy impact in performance.
Yes it is possible, if the instance of B is inside class A, it will get garbage collected automatically when A is destroyed. This example can be implemented this way:
public class A {
` B b;
public A(B b) {
this.b =b;
}
}
public class Test() {
public static void main(String [] args) {
A a = new A();
}
}
When a goes out of scope, both a and b will get garbage collected(object b inside a will be garbage collected first).
I don't think you can call garbage collector for an specific object, it works automatically as needed(You cant force that). You can try to invoke it this way:
Runtime r = Runtime.getRuntime();
r.gc();
It is not guaranted that the objects will be garbage callected when you execute the above code(Maybe the garbage collector is bussy)
There are no events fired when an object is finalized, except a (non-guaranteed) call to obj.finalize().
You may place some code to finalize() of A. If you can somehow deduct the object B based on object A data (but not keeping an actual reference), you may at this point remove B from a global static Set, making it eligible for GC (not necessary at the same GC run though).

Categories

Resources