Garbage collector in java - set an object null

2020-01-23 04:43发布

Lets assume, there is a Tree object, with a root TreeNode object, and each TreeNode has leftNode and rightNode objects (e.g a BinaryTree object)

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

6条回答
劫难
2楼-- · 2020-01-23 04:51

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.

查看更多
Fickle 薄情
3楼-- · 2020-01-23 04:53

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.

查看更多
走好不送
4楼-- · 2020-01-23 04:55

In Java, you do not need to explicitly set objects to null to allow them to be GC'd. Objects are eligible for GC when there are no references to it (ignoring the java.lang.ref.* classes).

查看更多
Deceive 欺骗
5楼-- · 2020-01-23 04:55

An object gets collected when there are no more references to it.

In your case, the nodes referred to directly by the object formally referenced by myTree (the root node) will be collected, and so on.

This of course is not the case if you have outstanding references to nodes outside of the tree. Those will get GC'd once those references go out of scope (along with anything only they refer to)

查看更多
兄弟一词,经得起流年.
6楼-- · 2020-01-23 04:58

myTree is just a reference variable that previously pointed to an object in the heap. Now you are setting that to null. If you don't have any other reference to that object, then that object will be eligible for garbage collection.

To let the garbage collector remove the object myTree just make a call to gc() after you've set it to null

myTree=null;
System.gc();

Note that the object is removed only when there is no other reference pointing to it.

查看更多
我命由我不由天
7楼-- · 2020-01-23 05:02

You can't set an object to null, only a variable which might contain an pointer/reference to this object. The object itself is not affected by this. But if now no paths from any living thread (i.e. local variable of any running method) to your object exist, it will be garbage-collected, if and when the memory is needed. This applies to any objects, also the ones which are referred to from your original tree object.

Note that for local variables you normally not have to set them to null if the method (or block) will finish soon anyway.

查看更多
登录 后发表回答