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?
Related
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!
I sometimes see the code of this kind in some library APIs and just in someone's code:
class SomeClass {
private WeakReference<SomeObject> objectWeakReference; // initialized elsewhere
public boolean isObjectAttached() {
return objectWeakReference.get() != null;
}
public SomeObject getObject() {
return objectWeakReference.get();
}
}
and
public void checkAndGetWeakReference() {
SomeClass someClass = new SomeClass();
if (someClass.isObjectAttached()) {
someClass.getObject().doSomethingDirectlyOnReturnedObject(); // can the returned reference be null here ?
}
}
And I'm always worried if there could be NullPointerException once in a blue moon, assuming there are no strong reference to the underlying object at this point.
I don't really know when exactly Garbage Collector can start deleting objects from memory and how does it correlate with the basic thread flow.
It would be nice if someone can shed the light on this particular subject and/or provide some information about the topic.
P.S. I would personally get reference only once and assign it to strong reference. The point of the question is to get some proof the code above is wrong.
The whole point of the WeakReference (and SoftReference as well) is that the referred object may be gc'd at any time no strong reference to the object exists.
Since there exists no strong reference when isObjectAttached() returns, yes it can be garbage collected before it actually gets to execute getObject(). The whole idom is faulty for this use case.
The only safe way is to first get the reference (e.g. to a local variable) and then check it against null. The object can then not be garbage collected in that case, because a local variable is a strong reference.
As per java doc. You should not rely on Garbage collector. Its not sure when it will be executed. Though you are trying explicitly System.gc()
Its always been a lowest priority for JVM for garbage collector. When JVM is free or when your program is around to ran out of memory it can execute GC.
In other case when your program will exit. It will be garbage collected before it is flushed out of JVM memory.
Please refer javadoc for detailed explanation for GC.
http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
I would like to add something to all answers.
Your object can be null when you call below method :
public SomeObject getObject() {
return objectWeakReference.get();
}
about garbage collection of this object.
If you do something like below :
public static void main(String args[]) {
SomeClass oSomeClass = new SomeClass();
// this one is strong reference "obj"
// this object can be null. Best practice is to null check before you use it.
// Or i will suggest to call isObjectAttached() method before you use it
Object obj = oSomeClass.getObject();
}
When you do obj = null; somewhere in code after above statement.
This object memory is available for garbage collection. Whenever JVM feels to clean memory. Yes it can collect this object.
Regarding proof of code you are asking.
public boolean isObjectAttached() {
return objectWeakReference.get() != null;
}
This method is made for you to check whether this object is present in memory or it has a valid reference for you.
If it returns true you will never get nullpointer exception.
but if you are not using this method i will suggest to use null check always before you use your object.
Hope I am on right direction and making some sense in my answer. Please respond accordingly.
We all are here to learn ;-)
Enjoy Java, OOP concepts.
Garbage collector internally has its heuristics to collect soft/weak/phantom references. It will not collect those objects in subsequent GC calls. It tracks these objects until it reaches the threshold of that heuristics, GC is not allowed to collect these references.
I sometimes assume that if oldObject != newObject then the object has changed - which seems a fair assumption in most cases but is it truly a bad assumption?
In short, under what situation could the following code print "Same!"?
static WeakReference<Object> oldO = null;
...
Object o = new Object();
oldO = new WeakReference(o);
// Do some stuff with o - could take hours or even days to complete.
...
// Discard o (or let it go out of scope).
o = null;
// More stuff - could be hours or days later.
...
o = new Object();
// Later still.
if ( o == oldO.get() ) {
System.out.println("Same!");
}
I realise that this is indeed remotely possible because an object reference is essentially the memory address of the object (or could be in some JVM). But how likely is it? Are we talking decades of run-time before it actually happens?
Added
My apologies - please assume that oldO is some form of weak reference that does not stop it from being collected. Perhaps it is Weak as the code (now) suggests or the reference is store in a database or a file somewhere.
(I'm answering what I think what you really wanted to know, rather than the particular snippet you have)
It's implementation dependant. The contract of object reference is that as long as the object is still alive, no other object will compare == with it. This implies that after the object is garbage collected, the VM is free to reuse the same object reference.
Implementation of Java may choose to use an increasing integer for object reference, in which case you can only get the same object reference when the reference counter overflows back to 0. Other implementation may use memory location, which makes it more likely for the same reference to be reused. In any case, you should define your own object identity if that matters.
never will it be the same. oldO will always reference the initial object so it will never be discarded and new object can't have same address.
UPDATE: seems like answer was updated to specify that oldO is a weak reference. In this case, when the object goes away, oldO's reference will become null. This means it will never match another object in the JVM.
It is not possible for them to be equal. You still have a reference to the old object (oldO), so it will never be discarded.
o == oldO means ois the same memory address as oldO. So, that cannot happen unless, at some time, you are doing either o = oldO or oldO = o. By transitivity, doing foo = o; oldO = foo or anything equivalent will achieve the same result, of course.
Firstly, memory address is irrelevant. Java ain't C. Object identity is a JVM implemention - it may, or may not, rely on memory address, but more likely does not, since the JVM is free to move the object around in memory but must maintain its identity.
But regardless. because you hold a reference to the original object, the second one can not be the "same" object.
It will never happen.
Your first object (oldO) is stored at a specific memory location.
Your second object will systematically be referenced at another memery location, as long as oldO is referenced.
So oldO == o will compare both memory addresses, which will always be different.
If you dereference oldO, it will be garbage collected, and you'll eventuelly be able to create a new object at this same address. But you won't be able to compare it with oldO, because it has been dereferenced.
By having a reference to your old object, you prevent it being garbage collected, so you prevent that bit of memory being available for a new object, so they could never be equal.
I wondered if you used a SoftReference you could keep a reference to the old object, while allowing it to be garbage-collected BUT:
1) I assume once the old object is collected, the SoftReference is set to null and
2) this is artificially trying to force the situation, so doesn't really prove anything :-)
According to the documentation, weak references will be cleared when the object is garbage collected. It does not specify what it means to be "cleared", but presumably it is set to null. If it is in fact set to null, null will never be declared == to any object reference, regardless of its memory location.
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.
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.