当我在Android上使用软引用时,遇到了一个奇怪的问题。我为位图缓存实现了一个类,源代码如下:
public class ImageCache
{
private static HashMap<String, SoftReference<Bitmap>> mCache = new HashMap<String, SoftReference<Bitmap>>();
private static final String TAG = "ImageCache";
public static Bitmap getBitmap(String url)
{
Bitmap bitmap = null;
if (mCache.containsKey(url))
{
Log.d(TAG, "use cache: " + url);
bitmap = mCache.get(url).get();
if (bitmap != null)
{
return bitmap;
}
else
{
Log.w(TAG, "#######################soft ref was collected!!!");
}
}
bitmap = BitmapFactory.decodeFile(url);
if (bitmap == null)
{
Log.e(TAG, "#####jpg not found");
return null;
}
bitmap = Bitmap.createScaledBitmap(bitmap, 320, 240, false);
synchronized (mCache) {
mCache.put(url, new SoftReference<Bitmap>(bitmap));
}
return bitmap;
}
}但我在日志中发现,软参考资料是经常收集的。日志是:
#######################soft ref was collected!!!据我所知,只有当java堆增长到极限且没有空间分配新内存时,GC才会收集软引用。
但是为什么Android上的软引用不像预期的那样呢?
发布于 2015-07-20 09:12:02
据我所知,只有当java堆增长到极限且没有空间分配新内存时,GC才会收集软引用。
这是错误的。
根据甲骨文文档的说法,任何给定的SoftReference都可以随时被收集,如果GC决定这样做的话。甚至还有VM参数,称为-XX:SoftRefLRUPolicyMSPerMB。因此,即使在桌面JVM上,在增加堆大小之前,SoftReferences也要被清除(有关此问题的一些额外细节,请参见这个问题 )。
Android 文档提供的保证甚至更少,而明确警告则更少保证VM不会坚持将这些引用保存太久:
与WeakReference不同的是,在运行时必须回收内存以满足分配之前,SoftReference才会被清除和排队。
我个人把它读成“直到下一个GC_FOR_ALLOC”。
当然,SoftReferences有一些有效的用途,例如使它们成为断路器。链接的文章还解释了为什么缓存不是其中之一。如果您想以某种方式管理缓存,这实际上很重要,请使用内存有限的LruCache,并从onLowMemory()中清除它。或者,更好的是,在使用了位图之后,让操作系统决定缓存什么,以及何时销毁应用程序,这些都是缓存。
https://stackoverflow.com/questions/31509201
复制相似问题