2

ビットマップをロードする必要のあるアプリケーションを開発しています。そしてSoftReference、キャッシュにを使用します。私はすべてのソフト参照をに関連付けReferenceQueue、ハッシュマップを使用してにアクセスしSoftReferenceます。次のように:

public static class MemCache {

    final private ReferenceQueue<Bitmap> queue = new ReferenceQueue<Bitmap>();
    private Map<String, SoftReference<Bitmap>> hash = null;

    public MemCache() {
        hash = Collections.synchronizedMap(
            new LinkedHashMap<String, SoftReference<Bitmap>>()
        );
    }

    public synchronized Bitmap put(String key, Bitmap value) {
        clean();
        SoftReference<Bitmap> ref = new SoftReference<Bitmap>(value, queue);
        SoftReference<Bitmap> res = hash.put(key, ref);
        if (res == null) return null;
        return res.get();
    }

    public synchronized Bitmap get(Object key) {
        clean();
        SoftReference<Bitmap> ref = hash.get(key);
        if (ref == null) return null;
        Bitmap val = ref.get();
        if (val != null) return val;
        hash.remove(key);
        return null;
    }
}

次に、私が次のように書くときclean()

    private synchronized void clean() {
        Reference<? extends Bitmap> sv;
        while ((sv = queue.poll()) != null)
            hash.remove(sv);
        Queue<String> toRemove = new LinkedList<String>();
        for(Entry<String, SoftReference<Bitmap>> e : hash.entrySet()){
            if(e.getValue()==null) continue;
            if(e.getValue().get()==null) 
                toRemove.add(e.getKey());
        }
        String s;
        while((s = toRemove.poll())!= null)
            hash.remove(s);
        Log.e("ImageCacheManager", "MemCache Size/2:" + new String(new char[hash.size() / 2]).replace("\0", "="));
    }

これは、ハッシュテーブル内のすべてのSoftReferencesがnullでないかどうかをチェックします。memcacheは良さそうですが、私が書いただけの場合:

    private synchronized void clean() {
        Reference<? extends Bitmap> sv;
        while ((sv = queue.poll()) != null)
            hash.remove(sv);
        Log.e("ImageCacheManager", "MemCache Size/2:" + new String(new char[hash.size() / 2]).replace("\0", "="));
    }

ReferenceQueueに入れられた要素を削除するだけで、ログはどんどん印刷されます=。多少の減少があっても、傾向は増加します。

http://www.ibm.com/developerworks/library/j-refs/に記載されているとおり

referentSoftReferencenullに設定されます。しかし、ほとんどはSoftReferenceにありませんでしたReferenceQueue。オブジェクトがファイナライズ可能としてマークされているがファイナライズされていない状態の間ですか?ファイナライズ可能としてマークされているがファイナライズされていないビットマップはリサイクルされますか?

4

1 に答える 1

5

私は同様の問題を実験しました。しばらくして、Androidがビットマップを管理する方法が原因であることに気づきました。私が誤解していないのであれば、彼らはビットマップにネイティブ実装である「skia」を使用しています。したがって、ビットマップはJavaヒープではなく、ネイティブヒープに割り当てられ、Javaビットマップオブジェクト自体は非常に小さく、GCの候補としては不十分です。そこで彼らは、ビットマップによって保持されているネイティブメモリを解放するリサイクルメソッドを提供しました。

英語が下手でごめんなさい。

于 2011-11-22T08:29:23.890 に答える