dra*_*fly 1 android soft-references
当我在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;
}
}
Run Code Online (Sandbox Code Playgroud)
但是我通过logcat发现经常会收集软引用。日志是:
#######################soft ref was collected!!!
Run Code Online (Sandbox Code Playgroud)
据我所知,仅当Java堆增长到其极限并且没有空间分配新的内存时,GC才会收集软引用。
但是,为什么Android上的软引用无法达到预期的效果?
据我所知,仅当Java堆增长到其极限并且没有空间分配新的内存时,GC才会收集软引用。
这是不正确的。
根据Oracle 文档,如果GC决定这样做,则可以随时收集任何给定的SoftReference。甚至还有VM参数,称为-XX:SoftRefLRUPolicyMSPerMB。所以SoftReferences是指以得到清除不必增加甚至在桌面上的JVM堆大小之前(也看到了这个问题对此事的一些额外的细节)。
Android 文档甚至提供了更少的保证,并明确警告,VM实际上不会坚持长时间保留这些引用:
与WeakReference不同,SoftReference在运行时必须回收内存以满足分配之前不会被清除和排队。
我个人将其称为“直到下一个GC_FOR_ALLOC”。
当然,SoftReferences有一些有效的用法,例如使它们成为断路器。链接的文章还解释了为什么缓存不是其中之一。如果您想以某种方式管理高速缓存,那实际上很重要,请使用内存受限的LruCache,然后从中清除onLowMemory()。或者,更好的是,在使用完位图后就放开它们,让操作系统决定要缓存的内容以及何时破坏应用程序及其缓存。
| 归档时间: |
|
| 查看次数: |
1163 次 |
| 最近记录: |