kir*_*tsz 2 java android garbage-collection out-of-memory soft-references
我正在开发一个需要加载Bitmap的应用程序.并使用一个SoftReference缓存.我将每个软引用与a相关联,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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,当我写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", "="));
}
Run Code Online (Sandbox Code Playgroud)
其中检查哈希表中的所有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", "="));
}
Run Code Online (Sandbox Code Playgroud)
其中只删除已放入ReferenceQueue的元素Log然后会打印越来越多=,甚至有一些减少,趋势是增加
正如http://www.ibm.com/developerworks/library/j-refs/中提到的那样
该referent的SoftReference设置为null.但大部分SoftReference都不在ReferenceQueue.在对象被标记为可终结但未最终确定的状态之间?将Bitmap标记为可终结但未最终确定是否已被回收?
我已经尝试过类似的问题.过了一段时间,我意识到这是因为android管理位图的方式.如果我没有误解他们使用"skia",一个本地实现,用于位图.因此位图不是在java堆中分配的,而是在本机堆中,并且java位图对象本身非常小并且不适合GC.因此,他们提供了循环方法,释放位图保留的本机内存.
抱歉我的英语不好.
| 归档时间: |
|
| 查看次数: |
5117 次 |
| 最近记录: |