java中的垃圾收集器-将对象设置为null [英] Garbage collector in java - set an object null

查看:42
本文介绍了java中的垃圾收集器-将对象设置为null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设有一个 Tree 对象,有一个 TreeNode 根对象,每个 TreeNode 都有 leftNode 和 rightNode 对象(例如一个 BinaryTree 对象)

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)

如果我打电话:

myTree = null;

树中相关的 TreeNode 对象到底发生了什么?也会被垃圾收集,或者我必须将树对象内的所有相关对象设置为空??

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

推荐答案

Java 中的垃圾收集是基于可达性"进行的.JLS 对该术语的定义如下:

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

可达对象是可以在任何活动线程的任何潜在持续计算中访问的任何对象."

只要对象可达1,它就没有资格进行垃圾回收.

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

JLS 将它留给 Java 实现来确定如何确定对象是否可以访问.如果实现不能确定,则可以自由地将理论上不可到达的对象视为可到达……而不是收集它.(实际上,JLS 允许实现永远不收集任何东西!虽然2没有实际的实现会这样做.)

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

在实践中,(保守的)可达性是通过tracing计算的;查看从类(静态)变量和线程堆栈上的局部变量开始的引用可以达到什么.

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.

这对您的问题意味着:

如果我调用:myTree = null; 树中相关的 TreeNode 对象到底发生了什么?也会被垃圾收集,或者我必须将树对象内的所有相关对象设置为空??

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

让我们假设 myTree 包含对树根的最后一个剩余可访问引用.

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

  1. 没有什么立即发生.
  2. 如果内部节点之前只能通过根节点访问,那么它们现在无法访问,并且有资格进行垃圾回收.(在这种情况下,不需要将 null 分配给对内部节点的引用.)
  3. 但是,如果内部节点可通过其他路径到达,则它们可能仍然可达,因此不符合垃圾收集条件.(在这种情况下,将 null 分配给对内部节点的引用是错误的.您正在分解一个数据结构,以后可能会尝试使用其他东西.)
  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.)

如果myTree 包含对树根的最后剩余可到达的引用,那么将内部引用归零也是一个错误原因同上.

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.

那么什么时候应该null来帮助垃圾收集器?

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. 类变量中的对象引用......(根据定义)永远不会超出范围.
  2. 局部变量中的对象引用仍在作用域内......但不会被使用.例如:

  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;
 }

在上面,我们知道如果 pigsMightFly 为 false,则不会使用列表对象.但是没有主流的 Java 编译器能够解决这个问题.

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.

实例变量或数组单元中的对象引用,其中数据结构不变量意味着它们不会被使用.@edalorzo 的堆栈示例就是一个例子.

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'
}

某些 Java 编译器/运行时可能能够检测到循环结束后不需要 'o',并将变量视为死变量.

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 - 事实上,我们在这里谈论的是可达性.当您考虑软引用、弱引用和幻像引用时,GC 可达性模型会更加复杂.但是,这些与 OP 的用例无关.

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 - 在 Java 11 中有一个名为 的实验性 GCEpsilon GC 明确不收集任何东西.

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

这篇关于java中的垃圾收集器-将对象设置为null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆