Suppose we have a class:
public class test{
public String member;
public test()
{
member = new String("internal object");
}
};
If I wrote this :
String refToUnreferencedClassMember = new test().member;
Is this problematic? The unreferenced object new test() has no reference pointing to itself, but there is a reference pointing to it's member object String member. If the unreferenced object is garbage collected, then refToUnreferencedClassMember will be invalid.
Thanks for your help. I don't know whether garbage collection will take place in this situation.
In this particular case,
new test().member;
will point to a String object in java heapspace.
Now when you assign it to
refToUnreferencedClassMember
then that String object would have two references i.e. one via anonymous new test() object and another via refToUnreferencedClassMember.
Note that test object would be eligible for GC. And when the anonymous new test() object is GC'd, your string object would still have one reference left i.e. refToUnreferencedClassMember, thus not allowing it to be GC'd.
Is this problematic?
No.
The unreferenced object new test() has no reference pointing to itself, but there is a reference pointing to its member object String member.
Correct.
If the unreferenced object is garbage collected, then refToUnreferencedClassMember will be invalid.
No it won't, unless it is unreferenced. As it is referenced in your example, the problem disappears.
That field has no knowledge regarding that enclosing object.
Therefore that enclosing object is immediately eligible to be garbage collected.
That string stays until the reference to it goes away.
But please note: from the object oriented point of view, you really want to avoid exposing mutable fields of classes. Allowing other classes to manipulate the internal state of members is something to not do!
Related
This question arises when I am learning the LinkedList data structure. Assume every Link (or Node) is represented by an object which contains two fields, data & next points to the next link. If I want to delete a specific node, clearly I will update the previous Link's next field. But should I set deleted link's next field to null, so as to make sure it will be reclaimed by the garbage collector ?
If my description is not clear, I try to generalize (or simplify) my question. Suppose an object a1 of class A which has a field, which references another object a2 of the same class. If there is no reference to object a1, will it be eligible for garbage collector ? Or we must explicitly set reference field in a1 to be null ? (don't care about object a2, there are other references to it besides the reference field in a1).
Garbage collector ideally collect all objects, which are not reachable by program flow. Even if this object has references to everything in JVM.
Object becomes unreachable if all running threads of program don't contain any direct or indirect references to it.
Direct reference looks like this:
void main(String... args){
Object a = new Object(); // <- from here main thread of program
// has reference to object `a`
...
}
Indirect reference looks like this:
void main(String... args){
List b = new ArrayList();
b.add(new Object()); // <- here you can't access object by typing `a`
// as in previous example, but you can get access with `b.get(0);`
// so that object can be accessed indirectly -> it is reachable.
}
It also handles properly cases of big isles of objects, which have references to each other, but none of which is reachable from program flow anymore.
MyClass a = new MyClass();
MyClass b = new MyClass();
a.field = b;
b.field = a;
// at this point a and b are reachable so they cannot be collected
b = null;
// at this point b's object is reachable indirectly through `a.field`
// so neither a nor b can be collected
a = null;
// at this point you cannot reach neither a nor b
// so a and b can be garbage collected,
// despite the fact that a is referenced by b and vice versa
UPD: added examples, changed some words to make answer clearer.
Your object a1 can be collected even if its fields still reference other objects. You do not need to set its fields to null.
The garbage collector collects objects which are not reachable. An object can hold references to others and still be collected. An object may have references to it, from other non-reachable objects, and still be collected.
All orphan objects are automatically eligible for garbage collection. And you do not need to explicitility set reference to null (however it's a good coding practice).
When the garbage collector will run, it will see that now a1 needs to be garbage collected as there are no longer references to it.
Also it will remove the reference field in a1 pointing to object of a2
but still for a2 (as you have mentioned for a2 there are other references to it besides the reference field in a1) so it is not eligible for garbage collection, hence it remains.
I know how to leave a signal for the Garbage Collector to delete an object by setting its reference variable to null:
Player player_reference = new Player();
player_reference = null;
// Now the Garbage collector knows to release all the memory related to this object.
But how can I set the reference variable to null through the object's class?
class Player {
public void doSomthing() {
if(condition) {
// some code which set the reference variable to null.
}
}
}
I know how to leave a signal for the Garbage Collector to delete an object by setting his reference variable to null
That's not really a "signal" - it's just making sure that the variable in question doesn't prevent garbage collectio. You really, really need to be clear about the differences between variables, references and objects. This question is meaningless:
But how can i set the reference variable to null through the object class?
What reference? There could be multiple variables which all have values which are references to the same object. Or indeed there may be no such variables - you could be calling the method via some intermediate expression:
foo().bar().doSomething();
What variable you expect to be set to null in that case?
The object will be eligible for garbage collection when there's no way of getting to it any more in any thread. You don't need to manually delete it, or "signal" the garbage collector. It will just happen naturally.
If I have code similar to the following:
public Constructor(final Object o) {
taskSystem.add(new CycleTask(15, 15, -1) {
#Override
public void execute() throws Throwable {
//access o here every 15 cycles forever
}
});
}
When would o be garbage collected, if ever? Only when the task has been collected, or will it remain in memory forever because it's final?
o might get garbage collected once it is not reachable any longer, whether it is final or not. Obviously, as long as execute is running, if it needs to access o, it will prevent GC.
When execute is done running, and assuming you have not stored any references to o (for example in a collection), it will be flagged as ready for garbage collection.
When the anonymous class instance becomes eligible for garbage collection, if nothing else refers to the object that o referred to when the method was called, that object will become eligible for garbage collection.
There's nothing special about final variables which deters garbage collection.
'final' has no effect on GC. The object will become eligible for collection when it becomes unreachable. In this case there are at least three references, any one of which can stop that: the 'final' parameter, which disappears when the method returns; the caller's reference; and the copy of the final variable in the anonymous class instance.
There is no relationship between final keyword and the lifetime of the variable.
It will be garbage collected when not needed anymore, and since it's a parameter this can happen just outside the method (if there is no reference outside).
The final keyword is just a constraint given to the compiler to forbid any further modification of the reference o after the call of the function.
Will the car_object_1 be able to garbage collected? Somebody maintain that as car_object_1 has two reference so it will never be garaged collected. Is it true?
Car createACar()
{
Car c = new MyCar(); //car_object_1 was created
return c;
}
void use_the_car()
{
Car c2 = createACar();
c2.run();
}
No, they're talking nonsense. Assuming there's nothing within run() which stashes a reference somewhere, the car is eligible for garbage collection after the c2.run(); statement in use_the_car.
Java is not reference counted - even circular references aren't a problem (e.g. where a Car and a Driver have a reference to each other, but nothing has a reference to either of them).
Perhaps the person you were talking to was thinking of a slightly different situation?
In Java, what is an unreachable object? When does the object become unreachable? While studying garbage collection I was not able to understand this concept.
Can anyone give any ideas with examples?
When there are no longer any reference variables referring to it, OR when it is orphaned in an island.
An island being an object that has a reference variable pointing to it, however that object has no reference variables pointing to it.
class A { int i = 5; }
class B { A a = new A(); }
class C {
B b;
public static void main(String args[]) {
C c = new C();
c.b = new B();
// instance of A, B, and C created
c.b = null;
// instance of B and A eligible to be garbage collected.
}
EDIT: Just want to point out that even though the instance of A has a reference, it is on an island now because the instance of B does not have a reference to it. The A instance is eligible for garbage collection.
An object is unrechable when there are no more references to it, or those references are themselves from unrechable objects.
Integer i = new Integer(4);
// the new Integer object is reachable via the reference in 'i'
i = null;
// the Integer object is no longer reachable.
in the object graph when one is not linked to it, then the reference become unreachable. then then the garbage collector scans for these dangling orphan objects and swipe out regaining allocated memory.
java.lang.ref.{Phantom,Soft,Weak} Reference Enqueues unreachable objects.
If the finalizer is run, the GC already knows its unreachable.
read about finalization- http://java.sun.com/developer/technicalArticles/javase/finalization/
In a language which has only strong references, heap objects can either be reachable or unreachable from the
program. The set of reachable objects is determined by the set of class variables and method variables in the program
pointing to heap objects. This set is usually referred to as the root set of the program. An object pointed by a variable
in the root set of the program is reachable. In addition, an object might be indirectly reachable. That is, an object is
reachable if there is another reachable object pointing to it. Such chain of references from the root set of the program
to a heap object is called reachability path. An object may have more than one reachability path to it as well as have
no reachability paths at all. If the object has no reachability paths it is deemed garbage and can be immediately
collected by the garbage collector.
An object enters an unreachable state when no more strong references to it exist. When an object is unreachable, it is a candidate for collection. Note the wording: Just because an object is a candidate for collection doesn't mean it will be immediately collected. The JVM is free to delay collection until there is an immediate need for the memory being consumed by the object.
It's important to note that not just any strong reference will hold an object in memory. These must be references that chain from a garbage collection root. GC roots are a special class of variable that includes
Temporary variables on the stack (of any thread)
Static variables (from any class)
Special references from JNI native code
more if you like to http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html
An unreachable object, is an object that doesn't have a "reachable" reference to it.
In other words, no references to it.