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.

Answer from Jon Skeet on Stack Overflow
Top answer
1 of 7
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.

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

🌐
Coderanch
coderanch.com › t › 386100 › java › Setting-objects-null
Setting objects to null (Java in General forum at Coderanch)
If the reference is an instance variable, then setting it to null makes the object available for GC as long as there are no other references to it. However, if you set an instance variable to null, no other method in the class will be able to access that object using that variable.
🌐
Net Informations
net-informations.com › java › cjava › objectonull.htm
How setting an Object to null help Garbage Collection?
The purpose of nulling is to assist the garbage collector in reclaiming memory by making objects unreachable earlier. In modern Java garbage collection, the process is optimized, and objects are typically cleaned up shortly after they become unreachable. This occurs when local variables go out of scope upon method completion or when a class instance is no longer referenced for fields. However, explicitly setting a reference to null instead of letting the variable go out of scope does not significantly assist the garbage collector unless the object held is exceptionally large.
🌐
Oracle
docs.oracle.com › cd › E19159-01 › 819-3681 › abebi › index.html
Assign null to Variables That Are No Longer Needed (Sun Java System Application Server 9.1 Performance Tuning Guide)
Explicitly assigning a null value to variables that are no longer needed helps the garbage collector to identify the parts of memory that can be safely reclaimed. Although Java provides memory management, it does not prevent memory leaks or using excessive amounts of memory. An application may induce memory leaks by not releasing object ...
🌐
DZone
dzone.com › coding › languages › null object pattern in java
Null Object Pattern in Java
August 22, 2018 - In this tutorial, we demonstrate how to use the null object pattern in Java, which depends on the Factory class and Optional class to represent non-null values.
🌐
Stack Overflow
stackoverflow.com › questions › 53775612 › java-set-object-attribute-to-null
Java - set object attribute to null - Stack Overflow
2 Assigning an Object to null is a code smell. Consider refactoring · 20 Garbage collector in java - set an object null · 1 java assign property when the value is not null · 1 Problems with declaring object to null · 27 clearing or set null to objects in java ·
Find elsewhere
Top answer
1 of 6
79

It depends a bit on when you were thinking of nulling the reference.

If you have an object chain A->B->C, then once A is not reachable, A, B and C will all be eligible for garbage collection (assuming nothing else is referring to either B or C). There's no need, and never has been any need, to explicitly set references A->B or B->C to null, for example.

Apart from that, most of the time the issue doesn't really arise, because in reality you're dealing with objects in collections. You should generally always be thinking of removing objects from lists, maps etc by calling the appropiate remove() method.

The case where there used to be some advice to set references to null was specifically in a long scope where a memory-intensive object ceased to be used partway through the scope. For example:

{
  BigObject obj = ...
  doSomethingWith(obj);
  obj = null;             <-- explicitly set to null
  doSomethingElse();
}

The rationale here was that because obj is still in scope, then without the explicit nulling of the reference, it does not become garbage collectable until after the doSomethingElse() method completes. And this is the advice that probably no longer holds on modern JVMs: it turns out that the JIT compiler can work out at what point a given local object reference is no longer used.

2 of 6
26

No, it's not obsolete advice. Dangling references are still a problem, especially if you're, say, implementing an expandable array container (ArrayList or the like) using a pre-allocated array. Elements beyond the "logical" size of the list should be nulled out, or else they won't be freed.

See Effective Java 2nd ed, Item 6: Eliminate Obsolete Object References.

Top answer
1 of 7
16

No, because a is a reference (not an object as in this question's title) and no method can modify the value of a reference except the method in which it is defined (I assume from the code context that a is a local variable).

Since Java doesn't have pass-by-reference, what you ask cannot be done: there's no way to collect addresses-of references in order to manage the addresses pointed to. You might use a wrapper object, but not sure what'd be the point.

2 of 7
5

As everyone else has said, this simply isn't possible. If it's cleaning up resources you're after, then you might consider using a pattern such as:

class A {

    private boolean cleanedUp;

    public void cleanUp() {
        // clean up any resources
        cleanedUp = true;
    }

    public boolean isCleanedUp() {
        return cleanedUp;
    }
}

And then using it like so:

A a = new A();
a.cleanUp();
if (a.isCleanedUp()) {
    ...
}

A better solution might be to implement the java.io.Closeable or java.lang.AutoCloseable interfaces depending on your circumstance:

class B implements AutoCloseable {

    private boolean closed;

    public boolean isClosed() {
        return closed;
    }

    @Override public void close() throws Exception {
        // clean up any resources
        closed = true;
    }
}

In which case you can use a try-with-resources statement:

try (B b = new B()) {
    // do stuff
} catch (Exception ex) {
    // oh crap...
}

Or you could even combine the two and do it that way, whichever you prefer.

Or lastly you could do it the way William Morrison explained (though I'd probably cheat and just use java.util.concurrent.atomic.AtomicReference instead of making my own class, and it comes with the added benefit of being a generified type), which, depending on your circumstance, may really be unnecessary. After all, you could always just do (even though it might seem a little odd):

A a = new A();

a.doStuffAndDisappear();
a = null;

if(a == null){
     //...
}
🌐
Quora
quora.com › In-Java-what-happens-to-an-object-reference-after-it-is-set-to-null
In Java, what happens to an object reference after it is set to null? - Quora
Answer: When object is assigned with some reference and then reference set to null then Garbace Collector (GC) check whether that object is assigned to other reference or not, if it is no assigned to any reference then this object is treated as unreachable object by GC, then GC destroyed this obj...
🌐
Saylor Academy
learn.saylor.org › mod › book › view.php
Strings and Object References in Java: The null Value
© Saylor Academy 2010-2024 except as otherwise noted. Excluding course final exams, content authored by Saylor Academy is available under a Creative Commons Attribution 3.0 Unported license. Third-party materials are the copyright of their respective owners and shared under various licenses.
🌐
Upwork
upwork.com › resources › articles › {name}
Null in Java: Understanding the Basics - Upwork
August 5, 2024 - For example, calling a method on a null object will throw an NPE. Default values. Uninitialized variables for reference types default to null, which can be useful but also requires careful null checks to prevent errors. Memory management. Using null helps manage memory by allowing the garbage collector to reclaim memory once a reference is set to null. Best practices for handling null in Java ...
🌐
SourceMaking
sourcemaking.com › design_patterns › null_object › java › 1
Null Object Design Pattern in Java
The advantage of this approach over a working default implementation is that a Null Object is very predictable and has no side effects: it does nothing. For example, a function may retrieve a list of files in a folder and perform some action on each. In the case of an empty folder, one response may be to throw an exception or return a null reference rather than a list.
🌐
GeeksforGeeks
geeksforgeeks.org › java › interesting-facts-about-null-in-java
Interesting facts about null in Java - GeeksforGeeks
September 3, 2024 - This allows a method to be called without specifying a value for that parameter, and the null value will be used instead. It is not recommended to use null as a value for a variable or object that is intended to hold a value of a primitive data type, such as int or double, because it will cause a compile-time error. The use of null in Java can be a source of confusion and subtle bugs, so it is important to be aware of its behavior and how to properly handle it in your code to prevent errors.
Top answer
1 of 6
34

Garbage collection in Java is performed on the basis of "reachability". The JLS defines the term as follows:

"A reachable object is any object that can be accessed in any potential continuing computation from any live thread."

So long as an object is reachable1, it is not eligible for garbage collection.

The JLS leaves it up to the Java implementation to figure out how to determine whether an object could be accessible. If the implementation cannot be sure, it is free to treat a theoretically unreachable object as reachable ... and not collect it. (Indeed, the JLS allows an implementation to not collect anything, ever! No practical implementation would do that though2.)

In practice, (conservative) reachability is calculated by tracing; looking at what can be reached by following references starting with the class (static) variables, and local variables on thread stacks.


Here's what this means for your question:

If i call: myTree = null; what really happens with the related TreeNode objects inside the tree? Will be garbage collected as well, or i have to set null all the related objects inside the tree object??

Let's assume that myTree contains the last remaining reachable reference to the tree root.

  1. Nothing happens immediately.
  2. If the internal nodes were previously only reachable via the root node, then they are now unreachable, and eligible for garbage collection. (In this case, assigning null to references to internal nodes is unnecessary.)
  3. However, if the internal nodes were reachable via other paths, they are presumably still reachable, and therefore NOT eligible for garbage collection. (In this case, assigning null to references to internal nodes is a mistake. You are dismantling a data structure that something else might later try to use.)

If myTree does not contain the last remaining reachable reference to the tree root, then nulling the internal reference is a mistake for the same reason as in 3. above.


So when should you null things to help the garbage collector?

The cases where you need to worry are when you can figure out that that the reference in some cell (local, instance or class variable, or array element) won't be used again, but the compiler and runtime can't! The cases fall into roughly three categories:

  1. Object references in class variables ... which (by definition) never go out of scope.
  2. Object references in local variables that are still in scope ... but won't be used. For example:

     public List<Pig> pigSquadron(boolean pigsMightFly) {
       List<Pig> airbornePigs = new ArrayList<Pig>();
       while (...) {
         Pig piggy = new Pig();
         ...
         if (pigsMightFly) {
           airbornePigs.add(piggy);
         }
         ...
       }
       return airbornePigs.size() > 0 ? airbornePigs : null;
     }
    

    In the above, we know that if pigsMightFly is false, that the list object won't be used. But no mainstream Java compiler could be expected to figure this out.

  3. Object references in instance variables or in array cells where the data structure invariants mean that they won't be used. @edalorzo's stack example is an example of this.

It should be noted that the compiler / runtime can sometimes figure out that an in-scope variable is effectively dead. For example:

public void method(...) {
    Object o = ...
    Object p = ...
    while (...) {
        // Do things to 'o' and 'p'
    }
    // No further references to 'o'
    // Do lots more things to 'p'
}

Some Java compilers / runtimes may be able to detect that 'o' is not needed after the loop ends, and treat the variable as dead.


1 - In fact, what we are talking about here is strong reachability. The GC reachability model is more complicated when you consider soft, weak and phantom references. However, these are not relevant to the OP's use-case.

2 - In Java 11 there is an experimental GC called the Epsilon GC that explicitly doesn't collect anything.

2 of 6
4

They will be garbage collected unless you have other references to them (probably manual). If you just have a reference to the tree, then yes, they will be garbage collected.