在Android上,软引用的行为不符合预期

在Android上,软引用的行为不符合预期,android,soft-references,Android,Soft References,我在Android上使用软引用时遇到了一个奇怪的问题。 我实现了一个位图缓存类,源代码如下: public class ImageCache { private static HashMap<String, SoftReference<Bitmap>> mCache = new HashMap<String, SoftReference<Bitmap>>(); private static final String TAG = "I

我在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;
    }
}
据我所知,只有当java堆增长到极限并且没有空间进行新的内存分配时,GC才会收集软引用

但为什么安卓系统上的软引用行为不符合预期

据我所知,只有当java堆增长到极限并且没有空间进行新的内存分配时,GC才会收集软引用

这是不正确的

根据甲骨文的说法,如果GC决定这样做,任何给定的SoftReference都可以随时收集。甚至还有一个VM参数,称为-XX:SoftRefLRUPolicyMSPerMB。因此,即使在桌面JVM上,软引用也意味着在必须增加堆大小之前被清除,请参阅,以获取有关此问题的更多详细信息

Android提供的保证更少,而且,虚拟机实际上不会长期坚持保留这些引用:

与WeakReference不同,SoftReference不会被清除和排队,直到运行时必须回收内存以满足分配

我个人把它读作直到下一个GC\U FOR\U ALLOC

当然,软引用也有一些有效的用途,例如使它们成为。链接文章还解释了为什么缓存不是其中之一。如果您想以一种真正重要的方式管理缓存,请使用内存有限的LruCache并从onLowMemory中清除它。或者,更好的办法是,在使用位图之后,让操作系统决定缓存什么以及何时销毁应用程序及其缓存

据我所知,只有当java堆增长到极限并且没有空间进行新的内存分配时,GC才会收集软引用

这是不正确的

根据甲骨文的说法,如果GC决定这样做,任何给定的SoftReference都可以随时收集。甚至还有一个VM参数,称为-XX:SoftRefLRUPolicyMSPerMB。因此,即使在桌面JVM上,软引用也意味着在必须增加堆大小之前被清除,请参阅,以获取有关此问题的更多详细信息

Android提供的保证更少,而且,虚拟机实际上不会长期坚持保留这些引用:

与WeakReference不同,SoftReference不会被清除和排队,直到运行时必须回收内存以满足分配

我个人把它读作直到下一个GC\U FOR\U ALLOC


当然,软引用也有一些有效的用途,例如使它们成为。链接文章还解释了为什么缓存不是其中之一。如果您想以一种真正重要的方式管理缓存,请使用内存有限的LruCache并从onLowMemory中清除它。或者,更好的办法是,在使用位图之后,让操作系统决定缓存什么以及何时销毁应用程序及其缓存。

位图的引用计数可能为0。。我想。软引用存储在McCache中,但我找不到对bitmapIt的其他引用。不建议将软引用用于缓存。改用LRUCache。位图的引用计数可能为0。。我想。软引用存储在McCache中,但我找不到对bitmapIt的其他引用。不建议将软引用用于缓存。使用LRUCache。如果软引用与弱引用几乎相同,那么定义两个几乎相同的引用的目的是什么?@dragonfly我已经在答案中阐明了这一部分。基本上,软引用至少在下一站(也称为收集一些垃圾以避免增加堆大小GC)之前不会被获取,而弱引用可能会在任何其他GC(如例程并行GC)期间被擦除。或者至少,文档的这一部分对我来说是这样的。我认为用于软引用的断路器应用程序只保留对您正在处理的数据的软引用,以避免OutOfMemoryErrors,这不是很好。A、 它是不完整的,因为文章本身指出,在某些时候,会有一个强有力的参考,这与目的背道而驰。B、 如果JVM恰好在某个时刻急于抛出一些数据,那么可能会导致操作失败——根本无法保证软引用的生存期。我还没有找到一个好的软件参考。使用强引用显式地自己管理缓存。如果软引用与弱引用几乎相同,那么定义两个几乎相同的引用的目的是什么?@dragonfly我已经在回答中阐明了这一部分。基本上,软引用至少在下一站(也称为收集一些垃圾以避免增加堆大小GC)之前不会被获取,而弱引用可能会在任何其他GC(如例程并行GC)期间被擦除。或者至少,文档的这一部分对我来说是这样的。我认为软引用的断路器应用程序只保留对数据的软引用 你正在努力避免OutOfMemoryErrors不是很好。A、 它是不完整的,因为文章本身指出,在某些时候,会有一个强有力的参考,这与目的背道而驰。B、 如果JVM恰好在某个时刻急于抛出一些数据,那么可能会导致操作失败——根本无法保证软引用的生存期。我还没有找到一个好的软件参考。使用强引用显式地自己管理缓存。
#######################soft ref was collected!!!