Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中使用弱引用的成本_Java_Garbage Collection_Weak References - Fatal编程技术网

在Java中使用弱引用的成本

在Java中使用弱引用的成本,java,garbage-collection,weak-references,Java,Garbage Collection,Weak References,有人研究过创建和垃圾收集Java对象所涉及的运行时成本吗?多线程应用程序是否存在任何性能问题(例如争用) 编辑:显然,实际答案取决于JVM,但也欢迎进行一般性观察 编辑2:若有人已经做了一些性能基准测试,或者可以指出一些基准测试结果,那个将是理想的。(很抱歉,奖金已过期…weakreference对CMS垃圾收集器有负面影响。据我所知,从服务器的行为来看,它会影响并行评论阶段的时间。在这个阶段,所有的应用程序线程都会停止,所以这是非常不受欢迎的事情。因此,您需要小心使用弱引用。如果应用程序是按需

有人研究过创建和垃圾收集Java对象所涉及的运行时成本吗?多线程应用程序是否存在任何性能问题(例如争用)

编辑:显然,实际答案取决于JVM,但也欢迎进行一般性观察


编辑2:若有人已经做了一些性能基准测试,或者可以指出一些基准测试结果,那个将是理想的。(很抱歉,奖金已过期…

weakreference对CMS垃圾收集器有负面影响。据我所知,从服务器的行为来看,它会影响并行评论阶段的时间。在这个阶段,所有的应用程序线程都会停止,所以这是非常不受欢迎的事情。因此,您需要小心使用弱引用。

如果应用程序是按需重建的,则使用弱引用的缓存可能会显著降低应用程序的速度,例如在Getter中:

public Object getSomethingExpensiveToFind() {
    if(cache.contains(EXPENSIVE_OBJ_KEY)) {
        return cache.get(EXPENSIVE_OBJ_KEY);
    }

    Object sth = obtainSomethingExpensiveToFind(); // computationally expensive
    cache.put(EXPENSIVE_OBJ_KEY, sth);
    return sth;
} 
想象一下这个场景:

1) 应用程序内存不足

2) GC清除弱引用,因此缓存也被清除

3) 应用程序继续,调用了许多方法,如getSomeThingExpensiveTofId()并重建缓存

4) 应用程序内存再次不足

5) GC清除磨损引用,清除缓存

6) 应用程序继续,许多方法(如GetSomeThingExpensiveTofId())被调用并再次重建缓存

7) 等等

我遇到了这样的问题——这个应用程序经常被GC中断,它完全破坏了缓存的全部功能


换句话说,如果管理不当,弱引用可能会降低应用程序的速度。

我曾经实现过一个Java垃圾回收器,因此我所能实现的只是一个(弱:)下限

在我的实现中,在垃圾收集期间访问每个弱引用时,都会有少量固定的额外开销

因此,结果是:我不会担心,这不是一个大问题,除非你使用了无数的弱引用

最重要的是,成本与存在的弱引用的数量成正比,而不是与整个堆的大小成正比

然而,这并不是说支持弱引用的垃圾收集器将和不支持弱引用的垃圾收集器一样快。这里假定的问题是,既然Java支持弱引用,那么使用它们的增量成本是多少

我的是一个简单的“停止世界”标记/清扫垃圾收集器。在垃圾收集期间,它会确定每个对象是否为活动对象,并在对象头中设置一个
live
位。然后它通过并释放所有非活动对象

要处理弱引用,只需添加以下内容:

  • 设置
    LIVE
    位时忽略弱引用(即,它们不会导致被引用对象上的
    LIVE
    位被设置)
  • 在扫描步骤中,添加如下特殊检查:如果您访问的对象是
    活动的
    ,并且是
    WeakReference
    ,则检查它弱引用的对象,如果该对象不是
    活动的
    ,则清除引用
这种逻辑的微小变化适用于软引用和幻影引用


如果你真的很好奇的话,实现就是了。

很抱歉,但我现在正试图找出在Sun论坛上出现这种行为的原因:)维塔利,你现在还有其他关于这个的吗?如果你在Sun论坛上找到了一些信息,你可以发布一个链接吗?谢谢它们有什么样的影响,显然是有代价的,因为gc需要特殊情况下的弱引用等。显然这将取决于JDK实现、Sun vs IBM vs JRockit等。在一篇文章中开始回答:在每次垃圾收集时,必须构造一个活动引用对象的列表,每个引用都必须进行适当的处理,这会给每个集合增加一些每个引用的开销,而不管当时是否正在收集引用。引用对象本身要进行垃圾收集,并且可以在引用对象之前进行收集,在这种情况下,引用对象不会排队。您基本上是说不明智地使用弱引用可能会对性能有害。。。由于对象缓存抖动。但问题是关于弱引用本身的开销。(理想情况下,我希望得到一个能给出这些间接费用的一些实际测量值的答案,但我也愿意接受一个权威性的解释,说明它们是如何产生的。)然后,你应该询问我具体做过的度量和基准。在奖金通知上。你读了吗?但无论如何,你的回答显然与所问的问题无关。这仍然是一个有用的观察结果,与讨论并不无关。@Will-这不是一个讨论论坛。这是一个问答网站。如果我想发起一场讨论,我会在另一个网站上提问。如果我想问使用参考资料是否是件好事。。。我会问另一个问题,这很有趣。(我认为热点实现是不同的。)如何处理finalize方法重新链接引用对象的情况?这难道不需要触发(部分)重新标记吗?我100%确信HotSpot的实现不仅不同,而且要复杂得多:)re:finalize,这只是非活动对象的一个额外步骤。它应该说的不是“它通过并释放所有非活动对象”“它通过并排队完成所有非活动对象”。Re:finalization,您必须在对象头中设置一个位,指示是否
finalize()
已被调用或未被调用,因此您不会按要求执行两次。因此,实际上,如果未设置位,则非
活动
对象将排队等待完成,如果已设置位,则立即释放。