软引用不表现在Android上如预期 [英] Soft reference does not behave as expected on Android

查看:111
本文介绍了软引用不表现在Android上如预期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我,当我在Android上使用软引用遇到了一个奇怪的问题。
我实现了一个类位图缓存,源$ C ​​$ c是如下:

 公共类ImageCache
{
    私有静态HashMap的<弦乐,SoftReference的<&位图GT;> mCache =新的HashMap<弦乐,SoftReference的<&位图GT;>();
    私有静态最后弦乐TAG =ImageCache;
    公共静态位图getBitmap(字符串URL)
    {
        位图位图= NULL;
        如果(mCache.containsKey(URL))
        {
            Log.d(TAG,使用缓存:+网址);
            位= mCache.get(URL)获得();
            如果(位图!= NULL)
            {
                返回位图;
            }
            其他
            {
                Log.w(TAG#######################收集软参考!!!);
            }
        }
        位= BitmapFactory.de codeFILE(URL);        如果(位图== NULL)
        {
            Log.e(TAG,##### JPG未找到);
            返回null;
        }
        位= Bitmap.createScaledBitmap(位图,320,240,FALSE);
        同步(mCache){
            mCache.put(网址,新SoftReference的<&位图GT;(位图));
        }
        返回位图;
    }
}

但我通过软引用经常收集logcat中找到。日志是:

  #######################收集软参考!

据我所知,软引用将被GC收集只有当Java堆增长到了极限,并有一个新的内存分配。

没有空间

但是,为什么预期在Android上的软引用不表现?


解决方案

  

据我所知,软引用将被GC收集只有当Java堆增长到了极限,并有一个新的内存分配。

没有空间

这是不正确。

据甲骨文文档 ,任何给定的SoftReference的可随时收集,如果GC使得决定这样做。甚至有一个VM参数,名为 -XX:SoftRefLRUPolicyMSPerMB 。所以SoftReferences是的意味着的得到清除不必增加,即使在桌面上的JVM堆大小之前(见这个问题对此事的一些额外的细节)。

文档使更少的保证,而<一HREF =htt​​ps://developer.android.com/training/displaying-bitmaps/cache-bitmap.html#memory-cache相对=nofollow>明确警告,该虚拟机实际上不会坚持围绕保持这些提法长:


  

不像WeakReference的,一个SoftReference的将不会被清零,直到排队运行时必须回收内存来满足分配。


我个人读作到明年 GC_FOR_ALLOC

有一定的SoftReferences一些有效的用途,如使之成为一个断路器。链接的文章还解释了,为什么缓存是不是其中之一。如果你要管理你的方式缓存,实际事务,使用内存限制 LruCache ,并明确表示,从 onLowMemory()。或者,更好的,只是放手位图的使用后,让OS决定,有什么缓存以及何时摧毁你的应用程序,它的缓存。

I encountered a strange problem when I was using soft reference on Android. I implemented a class for bitmap cache, the source code is as follows:

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;
    }
}

But I found through the logcat that soft reference is collected frequently. The log is:

#######################soft ref was collected!!!

As far as I know, soft reference will be collected by GC only if java heap grow to its limit and there is no space for a new memory allocation.

But why soft reference on Android does not behave as expected?

解决方案

As far as I know, soft reference will be collected by GC only if java heap grow to its limit and there is no space for a new memory allocation.

This is incorrect.

According to Oracle documentation, any given SoftReference may be collected anytime, if the GC makes decision to do so. There is even VM parameter, called -XX:SoftRefLRUPolicyMSPerMB. So SoftReferences are meant to get cleared before having to increase heap size even on desktop JVMs (see also this question for some extra details on the matter).

Android documentation gives even less guarantees, and clearly warns, that the VM won't actually insist on keeping those references around for long:

Unlike a WeakReference, a SoftReference will not be cleared and enqueued until the runtime must reclaim memory to satisfy an allocation.

Which I personally read as "until next GC_FOR_ALLOC".

There are certainly some valid uses for SoftReferences, such as making them a circuit breaker. The linked article also explains, why caching is not one of them. If you want to manage your cache in manner, that actually matters, use memory-limited LruCache and clear that from onLowMemory(). Or, better yet, just let go of Bitmaps after using them and let the OS decide, what to cache and when to destroy your application and it's caches.

这篇关于软引用不表现在Android上如预期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆