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

Fab*_*ndl 9 java android garbage-collection reference weak-references

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

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

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

  1. 只要对象没有更强的引用?(还没有发生GC)
  2. 或者当GC运行并确定它们不再是对象的强引用时?

如果2.是真的,那么我可能遇到我的缓存可能会填满并且GC最近因某些原因没有运行的情况.

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

Gab*_*han 10

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

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

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

  • 我不会说他们"没用".WeakReferences在Android中仍然有用,可以防止参考周期. (3认同)
  • 相同 - 只要没有强引用,它们就会被释放.这遵循Java标准的字母,如果不是精神. (2认同)

And*_*mas 5

一旦GC确定对象是弱可达的,就会清除WeakReference.

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

java.lang.ref的Java包文档中:

在将收集器添加到注册它们的队列(如果有)之前,软件和弱引用将由收集器自动清除.

...

如果一个对象既不强也不可轻易到达,则可以通过遍历弱引用来到达弱对象.当清除对弱可达对象的弱引用时,该对象将有资格进行最终确定.


小智 5

要缓存位图,请使用 SoftReference 而不是 Weak。GC 会在失去所有强引用和软引用时立即清除 WeakReference,这可能会破坏缓存的目的。SoftReference 仅在内存不足时清除。并且保证在抛出 OOME 之前运行 GC。