使用null然后GC的空闲堆内存

时间:2014-07-12 23:07:27

标签: java memory memory-management garbage-collection

假设我有这段代码:

DataStructure hugeData = Data.readLotsOfStuff(); // like gigabytes
DataStructure processedData = processData(hugeData);
// now I don't need hugeData, so
hugeData = null;
System.gc();

明确释放这样的记忆是一种好习惯吗?

1 个答案:

答案 0 :(得分:2)

关心这些事情通常不是一个好习惯。它使代码更难阅读(每个额外的行需要时间来阅读),并且在System.gc()的情况下,可能发生所有错误的运行时行为。它会混淆内部垃圾收集器的预测,并且通常会触发非常重/慢的GC。 (特别是如果你的代码用于并发使用的大型应用程序,那就太糟糕了。)

尽早解决局部变量(硬参考)存在问题:

a)如果您的引用仅用于某一点并且您的代码块更大,那么它可能太大了。

b)最好使局部变量最终,如果你知道变量没有改变,你可以更好地阅读代码。无论如何,这些最终变量都无法取消。

c)Java(运行时)编译器和解释器在一分钟内变得更加智能。让VM决定何时释放引用。

说完了这一切。如果将变量的范围/块保留在方法内,则不能指望引用的对象变得无法访问。将变量缩小范围看起来很好,但是对于早期释放引用的问题,它没有做太多(除非后面的范围重新使用该槽)。如果该方法长时间运行(可能是无限循环),则最好使引用无效。但只有当你引用一个非常大的对象树时才能保持对象的活着。否则额外的分配和代码是不值得的。

method() {
  if (...) {
    byte[] ref=new byte[1*MB];
  }
  // B
  while(true) { ... }
}

在这个例子中,大的1MB缓冲区不在位置'B'的范围内,但它仍然在运行时java堆栈上(java VM没有范围的概念,ref保存在局部变量表槽中直到方法离开了)。由于该方法不会(很快)终止,因此将其置零可能是可以接受的。拆分方法是更好的主意。

永远不要打电话给System.gc()。