WeakReference#get()什么时候开始返回null?

时间:2013-05-23 18:40:27

标签: java android reference garbage-collection weak-references

我想使用WeakReference s作为(android)位图缓存的一部分,以便能够检查何时不再使用位图。

我的缓存的最大大小小于Java堆空间。当一个新的位图溢出缓存时,它应该放弃不再需要的位图。

我的问题:WeakReference的get() - 方法什么时候返回null?

  1. 只要没有更强烈的对象引用? (还没有发生GC)
  2. 当GC运行并确定它们不再是对象的强引用时?
  3. 如果2.为真,那么我可能遇到我的缓存可能会填满并且GC最近因某些原因没有运行的情况。

    然后,即使我在上一次GC运行后已经放弃了引用,WeakReference#get()仍会返回该对象,我的缓存也不会清除它。

4 个答案:

答案 0 :(得分:10)

答案取决于您使用的Android版本。在2.3时间框架的某个地方,Android改变了它的处理或弱引用。以前,它在GC运行时删除了它们。从某些版本的2.3(2.3.3?)开始,它会在最后一次强引用后立即删除它们。所以在Android的现代版本中,弱引用是无用的。

在此更改之前,弱引用用于缓存。他们不再工作了。现在正确的方法是使用LRUCache。如果需要支持旧版本,请使用支持库来反向移植LRU缓存。

经过一番搜索,我认为改变是在3.0而不是2.3。不过,解决方案是一样的。

答案 1 :(得分:5)

一旦GC确定对象无法到达,就会清除WeakReference。

这接近你的第二个案例。然而,弱可达性不仅需要缺少强引用,还需要缺少软引用。

来自java.lang.ref的Java包文档:

  

收集器会自动清除软引用和弱引用,然后将其添加到注册它们的队列(如果有)。

     

...

     

如果某个对象既不强也不可轻松到达,则可以通过遍历弱引用来访问该对象。当清除对弱可达对象的弱引用时,该对象就有资格进行最终确定。

答案 2 :(得分:4)

要缓存位图,请使用SoftReference而不是Weak。一旦失去所有可能破坏缓存目的的强引用和软引用,GC就会清除WeakReference。只有在内存不足时才会清除SoftReference。并保证在投掷OOME之前运行GC。

答案 3 :(得分:-3)

如其他答案中所述,一旦指向对象没有更多强/软引用 GC已回收内存,WeakReference将返回null。

在更一般的规则上,我认为Weak / SoftReferences在应用程序中不是一件好事。它会引起你的混合问题:

  • 您的应用程序是关于业务逻辑的
  • JVM和Dalvik是关于内存管理和代码优化的。

当您开始使用弱/软引用时,您会在应用程序中引入内存管理的问题,这使得开发/调试/理解变得更加困难。

您可能希望使用固定大小(元素数或位图大小)LRU缓存。

希望有所帮助!