SoftReference太早收集垃圾

时间:2011-04-22 17:08:56

标签: java android garbage-collection soft-references

我正在为我的Android应用程序实现缓存机制。

我使用SoftReference,就像我发现的许多例子一样。问题是,当我在ListView中向上或向下滚动时,图像的最多已被清除。我可以在LogCat中看到每次应用程序加载新图像时我的应用程序都是垃圾回收。这意味着ListView中不可见图像的消失了。

所以,每当我向后滚动到之前的位置(之前我真的下载过图像)时,我必须再次下载图像 - 它们 缓存

我也研究过这个话题。 According to Mark Murphy in this articleSoftReference似乎存在(或者是?)错误。一些其他结果表明相同的事情(或相同的结果); SoftReference过早被清除。

有没有可行的解决方案?

5 个答案:

答案 0 :(得分:16)

SoftReference是可怜的勒芒。 JVM可以将这些引用保持更长时间,但不必。只要没有硬引用,JVM就可以垃圾收集软引用的Object。您遇到的JVM的行为是正确的,因为JVM不必更长时间地保持这样的对象。当然,大多数JVM都试图在某种程度上保持软参考对象的存活。

因此,SoftReferences是一种危险的缓存。如果您确实想要确保缓存行为,则需要一个真正的缓存。像LRU-cache一样。特别是如果你的缓存是性能关键的,你应该使用适当的缓存。

答案 1 :(得分:7)

来自Android培训网站:

http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

  

过去,流行的内存缓存实现是SoftReference   或WeakReference位图缓存,但不建议这样做。   从Android 2.3(API Level 9)开始,垃圾收集器更多   积极收集软/弱参考,使他们   相当无效。此外,在Android 3.0(API Level 11)之前,   位图的后备数据存储在本机内存中,而不是   以可预测的方式发布,可能导致应用程序   短暂地超过其记忆限制和崩溃。

链接中的更多信息。

我们应该使用LruCache代替。

答案 2 :(得分:2)

将每个图像缓存在持久存储上而不是仅存储在内存中。

答案 3 :(得分:1)

Gamlor的回答在你的情况下是正确的。但是,有关其他信息,请参阅问题32的GC FAQ

  

Java HotSpot Server VM使用最大可能的堆大小(由-Xmx选项设置)来计算剩余的可用空间。

     

Java HotSpot Client VM使用当前堆大小来计算可用空间。

     

这意味着服务器VM的一般趋势是扩展堆而不是刷新软引用,因此-Xmx对软引用何时被垃圾收集产生重大影响。

答案 4 :(得分:0)

Jvm按照以下简单公式确定是否应清除软引用:

时间间隔<= free_heap * ms_per_mb

interval是最后一个gc周期时间戳与软引用的最后访问时间戳之间的持续时间。 可用堆是那时可用的堆空间。 ms_per_mb是分配给堆中每个可用MB的毫秒数。 (恒定默认值为1000毫秒)

如果以上方程式为假,则引用将被清除。

因此,即使您有很多可用内存,如果您的软引用在足够长的时间内没有被访问,它们也会被清除。

-XX:SoftRefLRUPolicyMSPerMB = jvm arg可用于调整ms_per_mb常数。