【发布时间】:2012-01-03 15:32:17
【问题描述】:
我正在开发一个需要加载位图的应用程序。并使用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 是否不为空。 内存缓存看起来不错,但如果我只写:
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的元素
然后Log会打印越来越多=,虽然有一些减少,但有增加的趋势
正如http://www.ibm.com/developerworks/library/j-refs/中提到的那样
SoftReference 的referent 设置为空。但大部分SoftReference 不在ReferenceQueue 中。只是在对象被标记为可终结但未最终确定的状态之间?
标记为 finalizable 但未最终确定的 Bitmap 会被回收吗?
【问题讨论】:
-
会不会是linkedhashmap?我可能弄错了,但是因为映射的键不是软引用,所以 JVM 不会释放内存。它是指软引用的硬引用吗?
-
如果没有对位图的强引用,GC 会将 SoftReference
的引用设置为 null,则不会期望收集到它自己的 SoftReference 对象。我认为这可能不是 Bitmap Object 的内存没有被回收的原因
标签: java android garbage-collection out-of-memory soft-references