Android OOM以及GC的一些建议

cc68 5年前

  1. 这里有一个不错的文章在分析内存泄漏。它绝对可以帮助你.

  2. 你是否能保证你的SoftHashMap正常工作?看起来相当复杂。建议使用debugger来确保SoftHashMap中从未超过15个位图。 MAT也可以帮助你确定有多少位图出现在内存中。可以调用 cache.put(photoToLoad.url, bmp),来禁用内存缓存,确定否是有问题.

  3.  Activity leak   如果你只是在相同的activity中滑动发生OOM,这意味着有别的东西leaking 而不是activity 。如果停止/启动Activity几次,发现OOM仍然出现。那么查看MAT histogram 可以确定是否Activity leaking

  4. 当您使用图像的大小不是很确定时。应该要保证它的完美work,即使是 5m  px 这么大的图像。

  5. 你可以尝试只用 HashMap<String, SoftReference<Bitmap>>更换你的SoftReference的实现。这是良好的实现在内存缓存。它判断对象在内存中是否有足够的内存。如果内存太少,SoftReference释放的对象。

  6. 我推荐使用LinkedHashMap处理in-memory cache.。它有一个特殊的构造迭代在其中的最后一次访问顺序的entry。文档说,当你有超过15个项目在缓存中,你可以删除最近最少访问的项目。

  7. 如果你要加载更大的图像,你应该考虑清楚它们有多少内存消耗。如果太多,你可以只缓存他们SD卡,而不是内存中。这样做的话, 性能可能比较慢,但不会OOM

  8. 无关OOM。如果你调用clearCache() 在 onLowMemory()方法中。这样做不是一件好事,因为clearCache()也会删除SD缓存, 你要知道你要做的是清除内存缓存而不是SD缓存

分析heap,使用与jHat或Eclipse内存分析器(MAT)工具 </span>
  1. hprof-conv dump.hprof converted-dump.hprof 

Resource here:

  1. Here's an amazing article on analyzing memory leaks. It can definitely help you.

  2. Are you absolutely sure your SoftHashMap implementation works fine? Looks rather complicated. You can use debugger to ensure SoftHashMap never holds more than 15 bitmaps. MAT can also help you to identify how many bitmaps are there in memory.
    You can also comment cache.put(photoToLoad.url, bmp) call. This way you'll disable in-memory caching to identify if it's a cause of a problem or not.

  3. Yes it may be an Activity leak. You can identify that. If you just scroll around in the same activity and get OOM it means that something else is leaking not activity. If you stop/start activity several times and get OOM it means activity is leaking. Also you can definitely say is activity leaking or not if you take a look at MAT histogram.

  4. As you use inSampleSize the image size doesn't matter. It should work fine even with 5mpx images.

  5. You could try to replace your SoftHashMap implementation with just HashMap<String, SoftReference<Bitmap>>. Read about SoftReference. It is good for very simple implementation of in-memory cache. It holds objects in memory if there's enough memory. If there's too little memory SoftReference releases objects.

  6. I can also recommend you to use LinkedHashMap for in-memory cache. It has a special constuctor to iterate items in the order in which its entries were last accessed. So when you have more than 15 items in cache you can remove least-recently accessed items. As documentation says:

  7. You know my implementation was designed with small images in mind, something like 50*50. If you have larger images you should think how much memory they consume. If they take too much you could just cache them to SD card but not to memory. The performance may be slower but OOM would not be a problem any more.

  8. Not related to OOM. I can see you call clearCache() in onLowMemory(). Not good because clearCache() also removes cache from SD. You should only clear in-memory cache not SD cache.