我一直想知道为什么 Java 中的垃圾收集器会在需要时激活而不是激活:
if(obj.refCount == 0)
{
delete obj;
}
我忽略了Java如何做它有什么大的优势吗?
谢谢
我一直想知道为什么 Java 中的垃圾收集器会在需要时激活而不是激活:
if(obj.refCount == 0)
{
delete obj;
}
我忽略了Java如何做它有什么大的优势吗?
谢谢
每个 JVM 都不同,但 HotSpot JVM 并不主要依赖引用计数作为垃圾收集的手段。引用计数具有易于实现的优点,但它本质上容易出错。特别是,如果您有一个引用循环(一组在一个循环中相互引用的对象),那么引用计数将不会正确回收这些对象,因为它们都具有非零引用计数。这迫使您不时地使用辅助垃圾收集器,这往往会更慢(Mozilla Firefox 遇到了这个确切的问题,他们的解决方案是以增加代码可读性为代价添加垃圾收集器)。这就是为什么,例如,像 C++ 这样的语言倾向于组合shared_ptr
使用引用计数weak_ptr
的 s 和不使用引用循环的 s。
此外,将引用计数与每个对象关联会使分配引用的成本高于正常情况,因为调整引用计数涉及额外的簿记(在存在多线程的情况下只会变得更糟)。此外,使用引用计数排除了使用某些类型的快速内存分配器,这可能是一个问题。它还倾向于以幼稚的形式导致堆碎片,因为对象分散在内存中而不是紧密地打包,从而减少了分配时间并导致局部性差。
HotSpot JVM 使用各种不同的技术进行垃圾收集,但它的主要垃圾收集器称为停止和复制收集器。该收集器通过在内存中相邻分配对象来工作,并允许非常快速(一个或两个汇编指令)分配新对象。当空间用完时,所有新对象都会同时被 GC 处理,这通常会杀死大部分已构建的新对象。因此,GC 比典型的引用计数实现要快得多,并且最终具有更好的局部性和更好的性能。
为了比较垃圾收集技术,以及快速了解 HotSpot 中 GC 的工作原理,您可能需要查看我去年夏天教授的编译器课程中的这些讲座幻灯片。您可能还想查看HotSpot 垃圾收集白皮书,其中详细介绍了垃圾收集器的工作原理,包括基于应用程序调整收集器的方法。
希望这可以帮助!
引用计数有以下限制:
因为它不能严格基于引用计数来工作。
考虑不再从应用程序的“根”访问的循环引用。
例如:
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,您必须使用关键字等注释您的引用,strong
并weak
让 ARC 知道如何处理这些引用(并避免循环引用)......(不要对我使用 ARC 的具体示例读得太深,因为 ARC 会提前处理这些事情-of-time 在编译过程中并且不需要特定的运行时本身)所以它绝对可以像你描述它的方式一样完成,但它只是不适用于 Java 的某些特性。我也相信 COM 的工作方式与您描述的方式更相似……但同样,开发人员也没有考虑到这一点。
事实上,如果没有应用程序开发人员的一些思考(避免循环引用等),任何“简单”的引用计数方案都不可行
因为现代 JVM 中的垃圾收集器不再跟踪引用计数。该算法用于教授 GC 的工作原理,但它既耗费资源又容易出错(例如循环依赖)。
因为Java中的垃圾收集器是基于copying collector
“年轻一代”对象和
mark and sweep
“终身一代”对象的。
资源来自:http: //java.sun.com/docs/hotspot/gc1.4.2/faq.html