为什么JVM在引用计数达到0后立即销毁资源?

我一直想知道为什么Java中的垃圾收集器会在它感觉到而不是执行时激活:

if(obj.refCount == 0) { delete obj; } 

Java如何做到这一点有什么大的优势我忽略了吗?

谢谢

每个JVM都不同,但HotSpot JVM主要不依赖引用计数作为垃圾收集的手段。 引用计数具有易于实现的优点,但它本身容易出错。 特别是,如果您有一个引用循环(一组对象在一个循环中都相互引用),那么引用计数将无法正确回收这些对象,因为它们都具有非零引用计数。 这迫使你不时使用辅助垃圾收集器,这往往会更慢(Mozilla Firefox有这个问题,他们的解决方案是以很多代码可读性为代价添加垃圾收集器)。 这就是为什么,例如,像C ++这样的语言往往具有使用引用计数的shared_ptr和不使用引用循环的weak_ptr的组合。

此外,将引用计数与每个对象相关联会使分配引用的成本大于正常值,因为调整引用计数涉及额外的簿记(在multithreading存在时情况会变得更糟)。 此外,使用引用计数排除了快速使用某些类型的内存分配器,这可能是一个问题。 它也倾向于以天真的forms导致堆碎片,因为对象通过内存分散而不是紧密堆积,减少了分配时间并导致不良的局部性。

HotSpot JVM使用各种不同的技术来进行垃圾收集,但其主要垃圾收集器称为停止和复制收集器。 此收集器的工作原理是将对象在内存中相邻地分配,并允许极快(一个或两个汇编指令)分配新对象。 当空间用完时,所有新对象都同时进行GC操作,这通常可以杀掉大部分构建的新对象。 因此,GC比通常的参考计数实现快得多,并且最终具有更好的局部性和更好的性能。

有关垃圾收集技术的比较,以及HotSpot中GC的工作原理的快速概述,您可能希望查看我去年夏天教授的编译器课程中的这些演讲幻灯片 。 您可能还想查看HotSpot垃圾收集白皮书 ,该白皮书详细介绍了垃圾收集器的工作原理,包括逐个应用程序调整收集器的方法。

希望这可以帮助!

引用计数具有以下限制:

  • 这对于multithreading性能来说非常糟糕(基本上,必须保护对象引用的每个赋值)。
  • 你不能自动释放周期

因为它不能严格地根据引用计数工作。

考虑不再可以从应用程序的“根”访问的循环引用。

例如:

APP引用了SOME_SCREEN

SOME_SCREEN引用了SOME_CHILD

SOME_CHILD引用了SOME_SCREEN

现在, APP删除它对SOME_SCREEN的引用。

在这种情况下, SOME_SCREEN仍然具有对SOME_CHILD的引用,并且SOME_CHILD仍然具有对SOME_SCREEN的引用 – 因此,在这种情况下,您的示例不起作用。

现在,其他人(Apple与ARC,Microsoft与COM,以及其他许多人)都有解决方案,并且与您描述它的方式更相似。

使用ARC,你必须使用strongweak等关键字来注释你的引用,让ARC知道如何处理这些引用(并避免使用循环引用)…(不要过多介绍我的ARC特定示例,因为ARC处理这些在编译过程中提前完成的事情并不需要特定的运行时本身,所以它绝对可以像你描述的那样完成,但它对Java的某些function是不可行的。 我也相信COM的工作方式与你描述的方式更相似……但同样,开发人员并没有考虑到这一点。

实际上,如果没有应用程序开发人员的一些思考(避免循环引用等),任何“简单”引用计数方案都是行不通的。

因为现代JVM中的垃圾收集器不再跟踪引用计数。 该算法用于教导GC如何工作,但它既耗费资源又容易出错(例如循环依赖)。

因为java中的垃圾收集器基于’youg generation’对象的copying collector ,并且mark and sweep “tenure generation”对象。

资源来自: http : //java.sun.com/docs/hotspot/gc1.4.2/faq.html