Just wondering if that when you set
obj1 = null;
the object is eligible for gc, is it also true that everything with a null value is technically eligible also?
I'm particularly wondering about arrays, say if you have something like
[obj1, obj2, null, obj3, null, obj 4, obj5]
Can the gc run and remove the null object so the elements are empty?
Garbage collection collects objects, it does not collect references to objects. The idea of garbage collecting a null therefor makes no sense. What GC does at the simplest level is notice when an object no longer has any references pointing to it, and at that time it will free up the memory. It doesn't care how many references point to null, it only cares how many incoming references an object has.
SO no, GC will never remove nulls from an array. That's not what it does. Besides which, a null value in an array is perfectly valid and removing it would break many programs.
There is no "null object", and null is the closest thing that exists to an empty reference. The key definitions are in the Java Language Specification, 4.3.1. Objects:
An object is a class instance or an array.
The reference values (often just references) are pointers to these
objects, and a special null reference, which refers to no object.
obj1 = null; changes the reference variable obj1 to be null. If it previously referred to an object it no longer does so.
There may be other references that refer to that object, so that the object remains reachable, and the garbage collector will leave it alone. If obj1 was the last reference to the object, it is no longer reachable, and is eligible for finalization.
Related
I understand that when an object is added to a List, the List retains a reference to that object based on answer from this question
Is this java Object eligible for garbage collection in List
How then how do you make the object in the List eligible for garbage collection so that it's removed from the heap and not taking up memory?
I ask because in JavaFX, a Vboxs getChildren method returns observable list containing the children nodes of the vbox. If a UI element is removed but not eligible for garbage collection, will this object still be on the heap consuming memory?
Removing the references from that should make them subject of garbage collection (as long as no other object keeps references!).
You know, that is the whole idea how a GC works: it keeps those objects that are alive (can be reached from your initial starting point). Everything else is garbage; and subject to disposal once the GC decides to collect that garbage. And just to be precise here: you have to understand that these are two different activities. There might be a long time between object X "turns into garbage"; and "X gets collected; and memory is freed up".
One can use WeakReferences to avoid this; but of course, that requires that some piece of code would be pushing such WeakReference objects into the list initially. So, if you "own" this code, you could change that. But of course: that means that you always have to check if the object behind the WeakReference is still there when accessing the WeakReference.
How then how do you make the object in the List eligible for garbage
collection so that it's removed from the heap and not taking up
memory?
Assuming that those objects are only referenced by this List, simply use the clear method
If a UI element is removed but not eligible for garbage collection,
will this object still be on the heap consuming memory?
As long as an object is been hard referenced by at least one another object that is not itself eligible for garbage collection, the objet will be itself not eligible for garbage collection so it won't be collected by the GC it will then remain in the heap.
If you cannot remove the object from the List, the only way I can think about to handle this would be wrapping your Objects into a WeakReference.
Let's say I have a Vector v that contains 100 objects of class Scenario which is composed of 10 different types of objects.In order to permanently delete Scenario and all its objects at index 5 of Vector v , which one of the following is correct way.
1. v.removeElementAt(5);
OR:
2. Scenario s=(Scenario) v.elementAt(5);
v.removeElementAt(5);
s=null;
OR:
3. Scenario s=(Scenario) v.elementAt(5);
s.makeAllObjectsNull();//explicitly assign null to 10 objects inside Scenario e.g. object1=null object2=null and so on
v.removeElementAt(5);
s=null;
Does an object need to be explicitly deleted after deleting it from a Vector?
in simple word, all object that haven't any reference from another object is legible to be GC.
So any case of your code get that condition, then the object will be GC.
for example if a Scenario object has only referent from that vector, then:
v.removeElementAt(5);
the only reference has gone, and it will be legible to be GC.
another thing to tell here.
when you doing this:
Scenario s = (Scenario) v.elementAt(5);
v.removeElementAt(5);
s = null;
You just declared another reference s and then set it to null, so it's not necessary to this.
You never explicitly delete an object in Java. The garbage collector may automatically free an object's memory when it is no longer reachable. Usually you don't have to think about it, other than:
Some objects hold external resources other than memory. Those must be disposed of explicitly, sometimes through the java.io.Closeable interface.
Unintentional object retention can occur if a variable outlives the useful lifespan of the object to which it refers. In these cases, it can be useful to set the object to null. But these are the exception.
"Nulling out object references should be the exception rather than the norm. The best way to eliminate an obsolete reference is to let the variable that contained the reference fall out of scope. This occurs naturally if you define each variable in the narrowest possible scope." -- from "Effective Java," 2nd ed., by Joshua Bloch.
For your specific case:
Let's say I have a Vector v that contains 100 objects of class Scenario which is composed of 10 different types of objects.
Note that your vector does not contain objects. It contains references to objects. There may be other references to the same objects.
1.
v.removeElementAt(5);
This removes the reference to the object from the vector. The object is eligible for collection if no other references to it remain.
OR
Scenario s=(Scenario) v.elementAt(5);
v.removeElementAt(5);
s=null;
This has no value. It assigns an additional reference and promptly forgets that reference. Setting a single reference to null does not cause object disposal. The object is eligible for disposal if and only if there are no other external references.
OR
Scenario s=(Scenario) v.elementAt(5);
s.makeAllObjectsNull();//explicitly assign null to 10 objects inside Scenario e.g. object1=null object2=null and so on
v.removeElementAt(5);
s=null;
This is also unnecessary.
You don't have any objects inside the Scenario object. You may have references to objects. The garbage collector is looking for unreachable objects. It can handle disconnected graphs of references.
If the Scenario itself becomes unreachable, then setting its fields to null has no effect on the reachability of the objects referenced by its fields.
It depends on your case.
If u have no more links on scenario object and vector is a storage for your scenarios, then you can just remove it from collection and garbage collector remove it and its children elements from memory. It is the case of aggregation
If scenario is stored in some other storage and vector is used to associate your scenario with some other information (but scenario is stored under some other entity), then removing from vector means remove just association between your scenario and some info. Then scenario will stay in your system with all state. It is the case of composition
I have this confusion going on with HashMaps. If I have a HashMap let say HashMap. Then I add keys and values to HashMap like this
HashMap.put(1,myObj1);
HashMap.put(2,myObj2);
HashMap.put(3,myObj3);
Now if I do myObj1=null, the value is still available in the HashMap the reason I believe (correct me If I am wrong) myObj1 only contains a pointer (reference) to the place in memory. So in the HashMap the reference that myObj1 had was copied. As myObj1 is now pointing nowhere (null) but the copied value in the hashMap is still pointing to the memory location. So now what kind of reference is this Weak, Strong. Will myObj1 garbage collected if so the value it was pointing to ( the value hasHashMap still points too), what happens to that.
Any Object is candidate to be garbage collected only if no references point to it.
If you do the following:
Object myObj1 = ....
myMap.put(1,myObj1);
myObj1 = null;
You have the internal references from myMap to that myObj1.
When you leave the references to the myMap if no other reference (explicit or implicit) to myObj1 exists it become a candidate to be garbage collected.
So if you explicitly put to null the reference to myMap myObj become a candidate to gc.
Object myObj1 = ....
myMap.put(1,myObj1);
myObj1 = null; // myObj1 is not candidate to be gc
...
myMap = null; // myObj1 and myMap are candidates to be gc
The value in the HashMap implementation always has strong reference. What it means, unless you remove the element/map it won't be garbage collected. There is another implementation in java called WeakHashMap which store the key as weak reference. This key will be garbage collected regardless its removed from Map or not. Please note the value in WeakHashMap still has strong reference.
I was recently looking into freeing up memory occupied by Java objects. While doing that I got confused about how objects are copied (shallow/deep) in Java and how to avoid accidently clearing/nullifying objects while they are still in use.
Consider following scenarios:
passing a ArrayList<Object> as an argument to a method.
passing a ArrayList<Object> to a runnable class to be processed by a thread.
putting a ArrayList<Object> into a HashMap.
Now in these case, if I call list = null; or list.clear();, what happens to the objects? In which case the objects are lost and in which cases only the reference is set to null?
I guess it has to do with shallow and deep copying of objects, but in which cases does shallow copying happens and in which case does deep copy happens in Java?
Firstly, you never set an object to null. That concept has no meaning. You can assign a value of null to a variable, but you need to distinguish between the concepts of "variable" and "object" very carefully. Once you do, your question will sort of answer itself :)
Now in terms of "shallow copy" vs "deep copy" - it's probably worth avoiding the term "shallow copy" here, as usually a shallow copy involves creating a new object, but just copying the fields of an existing object directly. A deep copy would take a copy of the objects referred to by those fields as well (for reference type fields). A simple assignment like this:
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<String> list2 = list1;
... doesn't do either a shallow copy or a deep copy in that sense. It just copies the reference. After the code above, list1 and list2 are independent variables - they just happen to have the same values (references) at the moment. We could change the value of one of them, and it wouldn't affect the other:
list1 = null;
System.out.println(list2.size()); // Just prints 0
Now if instead of changing the variables, we make a change to the object that the variables' values refer to, that change will be visible via the other variable too:
list2.add("Foo");
System.out.println(list1.get(0)); // Prints Foo
So back to your original question - you never store actual objects in a map, list, array etc. You only ever store references. An object can only be garbage collected when there are no ways of "live" code reaching that object any more. So in this case:
List<String> list = new ArrayList<String>();
Map<String, List<String>> map = new HashMap<String, List<String>>();
map.put("Foo", list);
list = null;
... the ArrayList object still can't be garbage collected, because the Map has an entry which refers to it.
To clear the variable
According to my knowledge,
If you are going to reuse the variable, then use
Object.clear();
If you are not going to reuse, then define
Object=null;
Note:
Compare to removeAll(), clear() is faster.
Please correct me, If I am wrong....
It depends on how many variables are referenciating to each of your objects, to explain this it would be better some code:
Object myAwesomeObject = new Object();
List<Object> myList = new ArrayList<Object>();
myList.add(myAwesomeObject);
myList = null; // Your object hasn't been claimed by the GC just yet, your variable "myAwesomeObject" is still refering to it
myAwesomeObject = null; // done, now your object is eligible for garbage collection.
So it doesn't depend whether you pass your ArrayList as an argument to a method or the like, it depends on how many variables are still refering to your objects.
If you passed an ArrayList to a method then list = null will have no effect if there is a live reference to the list somewhere eg in the calling code. If you call list.clear() anywhere in the code the references to the objects from this list will be nulled. Passing a reference to a method is not shallow copying it is passing reference by-value
Java GC automatically claims the objects when they are not referenced anywhere. So in most cases you will have to set the reference as null explicitly
As soon as the scope of the variable ends the object becomes eligible for GC and gets freed up if no other reference points to the object.
Java is pass by value so if you set the list as null in the method then it will not affect the original reference that was passed to you in the method.
public class A{
private List<Integer> list = new ArrayList<Integer>();
public static void main(String[] args) {
A a = new A();
B b = new B();
b.method(a.list);
System.out.println(a.list.size()); //Will print 0 and not throw NullPointerException
}
}
class B{
public void method(List<Integer> list){
list = null;
//just this reference is set to null and not the original one
//so list of A will not be GCed
}
}
If you put the list into a hash map, the hash map now holds a reference to the list.
If you pass the list as an argument to a method, the method will have a reference to it for the duration of the method.
If you pass it to a thread to be manipulated, the thread will have a reference to the object until it terminates.
In all of these cases, if you set list = null, the references will still be maintained, but they will disappear after these references disappear.
If you simply clear the list, the references will still be valid, but will now point to a list that has suddenly been emptied, by means that may be unknown to the programmer and may be considered a bug, especially if you use the thread.
I was recently looking into freeing up memory occupied by java objects.
A piece of advice.
It is usually a bad idea to think about this. And it is usually a worse idea to try to "help". In 99.8% of cases, the Java garbage collector is able to do a better job of collecting the garbage if you actually just let it get on with it ... and don't waste your effort by assigning null to things. Indeed, the chances are that the fields you are nulling are in objects that are about to become unreachable anyway. And in that case, the GC is not even going to look at the fields that you've nulled.
If you take this (pragmatic) view, all your thinking about shallow versus deep copies and when it is safe to null things is moot.
There is a tiny percentage of cases where it is advisable to assign null ... to avoid medium or long term storage leaks. And if you are in one of those rare situations where it is "recycling" objects is actually a good idea, then nulling is also advisable.
All,
If I were to write a function to delete a node (given headNode and data as input parameters) from a linkedList in Java. I would find the node that has "node.data=data", and delete it by pointing its previous node to its next node *^. My question is, do we have to point the "to be deleted" node to null? to free the memory? or the GC will take care of objects no more accessed in heap.
*^: say A->B->C->D , if B.data=data, then make A->C . is B->Null necessary?
please let me know if its not clear, I will edit it. Thanks.
If you want to delete Node B you just need for A to point to C. The garbage collector will take care of your B nodes as there won't be any references left to it.
The following explanation is quoted from http://javarevisited.blogspot.com/2011/04/garbage-collection-in-java.html
An Object becomes eligible for Garbage collection or GC if its not reachable from any live threads or any static refrences in other words you can say that an object becomes eligible for garbage collection if its all references are null. Cyclic dependencies are not counted as reference so if Object A has reference of object B and object B has reference of Object A and they don't have any other live reference then both Objects A and B will be eligible for Garbage collection.
Generally an object becomes eligible for garbage collection in Java on following cases:
1) All references of that object explicitly set to null e.g. object = null
2) Object is created inside a block and reference goes out scope once control exit that block.
3) Parent object set to null, if an object holds reference of another object and when you set container object's reference null, child or contained object automatically becomes eligible for garbage collection.
4) If an object has only live references via WeakHashMap it will be eligible for garbage collection.
As everyone has said you don't need to set it to null. I just want to add that I had a similar question before which might not be obvious. If you have a doubly linked list, where each node references the previous and the next node, for example A-B-C-D and you remove C-D so that you're left with A-B. You also do not need to worry about C or D even though both of them still have a reference to them (from the other one). Apparently the GC is smart enough to take care of that case as well
No you don't have to set B to null. The Java garbage collector will free the memory for any object not reachable anymore.