clearing or set null to objects in java
Asked Answered
A

7

27

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:

  1. passing a ArrayList<Object> as an argument to a method.
  2. passing a ArrayList<Object> to a runnable class to be processed by a thread.
  3. 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?

Anthemion answered 2/8, 2013 at 6:12 Comment(1)
I always found one of the most appealing aspects of Java is the garbage collector...Affixation
H
59

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.

Hakenkreuz answered 2/8, 2013 at 6:19 Comment(6)
thnks for clearing it has nothing to do with shallow or deep copying!!Anthemion
Actually, what you say is kinda wrong ... the following code: ArrayList<String> list1 = new ArrayList<String>(); list1.add("yoyo"); list1.add("yoyo2"); System.out.println(list1.size()); ArrayList<String> list2 = list1; list1 = null; System.out.println(list2.size()); will print 2 2Gribble
@pinpinokio: Where does that contradict what I said? That's exactly what I'd expect it to print, and as far as I can see it doesn't go against anything in the answer. What do you think the answer would predict the result of that to be, and which section of the answer do you think is relevant to that?Hakenkreuz
Ah, yes, my mistake - I read your answer wrong - but is still a bit confusing, because someone with less knowledge, seeing "list1 = null;" could think that this made the "list2.size()" equal to 0 :) But yes, apologies, mistake is mine ...Gribble
@pinpinokio: It would be a very odd situation for setting one variable to null to clear a list. I think I'm happy with the clarity of the answer as it stands.Hakenkreuz
@JonSkeet setting one variable to null to clear a list is exactly what a newbie would do, so this is not that odd. And since this is a newbie question, I think it is normal to expect someone to understand it wrong - but yes, the clarity is good enough, so again - no need to change anything in the answer.Gribble
E
10

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....

Enforce answered 20/5, 2014 at 10:4 Comment(0)
D
2

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.

Deplete answered 2/8, 2013 at 6:18 Comment(1)
You forgot: myList.add(myAwesomeObject); :)))Marissamarist
P
2

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
    }
}
Pitchford answered 2/8, 2013 at 6:23 Comment(0)
T
2

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

Tractile answered 2/8, 2013 at 6:24 Comment(0)
I
1

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.

Intransigeance answered 2/8, 2013 at 6:21 Comment(0)
W
0

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.

Whither answered 2/8, 2013 at 6:58 Comment(3)
Could you please elaborate on "unreachable"? Does it mean that when a method ends all those local variables are elegible for gc ?Laocoon
Unreachable is a technical term; see stackoverflow.com/questions/5667705 for an explanation.Whither
You need to distinguish between variables and objects. Local variables are on the stack, and the stack is not subject to garbage collection. However, variables may contain references to objects, and objects are in the heap and >are< subject to garbage collection ... if they are unreachable.Whither

© 2022 - 2024 — McMap. All rights reserved.