在Java中使用弱引用的成本

时间:2009-08-09 03:27:06

标签: java garbage-collection weak-references

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

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

编辑2:如果有人对性能做了一些基准测试,或者可以指出一些基准测试结果,那将是理想的。 (对不起,但是赏金已经过期了......)

3 个答案:

答案 0 :(得分:13)

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

答案 1 :(得分:5)

我实现了一次Java垃圾收集器,所以无论我能做什么都是可能的(弱:)下限。

在我的实现中,在垃圾回收期间访问每个弱引用时,会有一小部分额外的开销。

结果就是:我不担心它,除非你使用数以万计的弱引用,否则这不是一个大问题。

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

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

我是一个简单的“停止世界”#34;标记/清除垃圾收集器。在垃圾收集期间,它会确定每个对象是否存在该对象,并在对象标头中设置LIVE位。然后它会通过并释放所有非实时对象。

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

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

此逻辑的微小变化适用于软和幻像参考。

如果您真的很好奇,请执行here

答案 2 :(得分:3)

使用弱引用的缓存可能会显着减慢您的应用,如果它按需重建,例如在吸气剂中:

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)应用程序继续,调用getSomethingExpensiveToFind()等许多方法并重建缓存

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

5)GC清除磨损参考,清除缓存

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

7)等等......

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

换句话说,如果管理不当,弱引用会降低您的申请速度。