繁体   English   中英

variable = null将其设置为垃圾回收

[英]Does variable = null set it for garbage collection

帮助我解决与同事之间的争议:在Java中将变量或集合设置为null有助于垃圾收集并减少内存使用吗? 如果我有一个长时间运行的程序,并且可以迭代地调用每个函数(可能数千次):在将值返回到父函数之前将其中的所有变量设置为null有助于减少堆大小/内存使用量吗?

这是旧表现的绝杀。 这在1.0天内确实如此,但编译器和JVM已得到改进,以消除需求(如果有的话)。 如果您感兴趣,这篇优秀的IBM文章会详细介绍: Java理论与实践:垃圾收集和性能

来自文章:

有一种情况是使用显式归零不仅有用,而且实际上是必需的,并且这是对对象的引用范围比程序规范使用或认为有效的范围更广。 这包括诸如使用静态或实例字段来存储对临时缓冲区的引用而不是本地变量的情况,或者使用数组来存储可以由运行时保持可访问而不是由程序的隐含语义可访问的引用。

翻译:“显式null”不再需要的持久对象。 (如果你愿意。“几乎要求”声明过于强烈?)

Java VM Spec

12.6.1实现终结每个对象都可以用两个属性来表征:它可以是可达的,终结器可达的,或者是不可达的,它也可以是未终结的,可终结的或最终的。

可到达对象是可以从任何活动线程的任何潜在继续计算中访问的任何对象 可以设计优化程序的转换,以减少可达到的对象的数量,使其少于可以被认为可达的对象的数量。 例如,编译器或代码生成器可以选择设置将不再用于null的变量或参数,以使得此类对象的存储可能更快地被回收。

讨论

如果对象字段中的值存储在寄存器中,则会出现另一个示例。 然后程序可以访问寄存器而不是对象,并且永远不会再次访问对象。 这意味着该对象是垃圾。

如果对象可以参与任何潜在的持续计算,则该对象是可达的。 因此,如果您的代码引用了局部变量,并且没有其他内容引用它,那么您可以通过将其设置为null来使对象收集。 这可能会给出一个空指针异常,或者改变程序的行为,或者如果它既没有,那么你首先不需要变量。

如果要将字段或数组元素归零,那么对于某些应用程序来说这可能是有意义的,并且它将使内存更快地被回收。 一旦case正在创建一个大型数组来替换类中某个字段引用的现有数组 - 如果创建了替换之前为空的字段,那么它可以减轻对内存的压力。

Java的另一个有趣特性是范围不会出现在类文件中,因此范围与可达性无关; 这两个方法创建相同的字节码,因此VM根本看不到所创建对象的范围:

static void withBlock () {
    int x = 1;

    {
        Object a = new Object();
    }

    System.out.println(x+1);
}

static void withoutBlock () {
    int x = 1;

    Object a = new Object();

    System.out.println(x+1);
}

不必要。 当没有活动线程持有对象的引用时,对象就有资格进行垃圾回收。

当方法返回时,局部变量超出范围,将局部变量设置为null完全没有意义 - 变量无论如何都会消失,如果没有其他任何东西保存引用变量引用的对象,那么这些对象变为有资格进行垃圾收集。

关键不是仅查看变量,而是查看这些变量引用的对象,并找出程序引用这些对象的位置。

它对局部变量没有用处,但它可能有用/需要清除不再需要的实例变量(例如,后初始化)。

(是的,我知道如何应用Builder模式...)

这可能只是使一些像这样的情景一定意义:

public void myHeavyMethod() {
  List hugeList = loadHugeListOfStuff();  // lots of memory used
  ResultX res = processHugeList(hugeList); // compute some result or summary 
  // hugeList = null;  // we are done with hugeList
    ...
  // do a lot of other things that takes a LOT of time (seconds?)
  // and which do not require hugeList
   ...
}

我猜这里取消注释hugeList = null可能会带来一些好处。

但是重写方法肯定会更有意义(可能重构为两个,或者指定一个内部范围)。

将对象引用设置为null仅使其符合垃圾回收的条件。 它不一定释放内存,这取决于垃圾收集器何时运行(取决于JVM)。 当垃圾收集器运行时,它通过仅删除有资格进行垃圾收集的对象来释放堆。

这是一件好事。 将对象设置为null时,可能会在即时GC循环中更快地对对象进行垃圾回收。 但是没有保证机制使得在给定时间收集对象垃圾。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM