在Java中使用弱引用的成本

有没有人研究了创build和垃圾收集Java WeakReference对象所涉及的运行时成本? multithreading应用程序是否存在性能问题(如争用)?

编辑:显然实际的答案将是JVM的依赖,但一般的意见也是受欢迎的。

编辑2:如果有人已经做了一些基准的performance,或者可以指出一些基准的结果,这将是理想的。 (抱歉,但赏金已过期…)

WeakReference对CMS垃圾回收器有负面影响。 据我所知,从我们的服务器的行为,它影响并行备注阶段时间。 在这个阶段,所有的应用程序线程都停止了,所以这是非常不可取的。 所以你需要小心WeakReferences。

我实现了一个Java垃圾收集器,所以无论我能够完成什么是可能的(弱)下界。

在我的实现中,在垃圾收集过程中访问每个弱引用时,会有less量的额外开销。

所以结果是:我不会担心,除非你使用了大量的弱引用,否则这不是一个大问题。

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

但是,这并不是说支持弱引用的垃圾收集器将会像没有引用的那样快。 这里推测的问题是,鉴于Java支持弱引用,使用它们的增量成本是多less?

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

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

  • 设置LIVE位时忽略弱引用(即,它们不会导致引用对象上的LIVE位被设置)。
  • 在扫描步骤中,添加一个特殊的检查如下:如果你正在访问的对象是LIVE ,并且是WeakReference ,那么检查它弱引用的对象,如果该对象不是LIVE ,清除引用。

这种逻辑的小变化适用于软和幻影参考。

如果你真的好奇,实现就在这里 。

使用弱引用的caching可能会显着减慢你的应用程序,如果它需要重build,例如在getters中:

 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清除弱引用,从而清除caching

3)应用程序继续,调用getSomethingExpensiveToFind()等许多方法并重buildcaching

4)应用程序再次在内存中运行不足

5)GC清除磨损引用,清除caching

6)应用程序继续,调用getSomethingExpensiveToFind()等很多方法并重新生成caching

7)等等…

我遇到了这样的问题 – 这个应用程序经常被GC打断,它完全打败了整个caching点。

换句话说,如果pipe理不当,弱引用会减慢你的应用程序。