我花了差不多一整天的时间试图找出Android内存泄漏的原因.我有多次打开/关闭的活动(使用计时器).过了一会儿我得到OutOfMemory错误:
每次活动开始时,我都看到Xamarin Profiler中的内存不断上升:
我确保没有属性或事件处理程序可能会卡在该活动中.我甚至删除了每个图像,按钮等,试图检测导致内存泄漏的原因.还是一样...
然后我做了主要活动GC.Collect()
的OnResume
方法(打开有问题的活动的方法).现在我可以看到内存正在上下移动.您可以在屏幕截图中看到结果:
根据Xamarin文档:
当次要堆的内存用完新分配时,GC将运行
但实际上并没有发生这种情况
您可能希望在帮助GC下的链接中进一步阅读:
The GC has an incomplete view of the process and may not run when memory is low because the GC doesn't know that memory is low.
和
Managed Callable Wrappers do not add additional instance members
基本上,看起来BaseActivity是一个Android Callable Wrapper(ACW),Mono GC不知道它有多大,所以它不知道调用垃圾收集器.从我收集的内容来看,ACW是一种实现Android界面的方式.
正如您所发现的,解决方案是在使用ACW时手动调用Xamarin文档中推荐的垃圾收集器.
http://developer.xamarin.com/guides/android/advanced_topics/garbage_collection/
----
自从这个答案的原始发布以来,Xamarin文档在解释这种情况方面有所改进:
Java.Lang.Object类型或派生类型的实例大小至少为20个字节.托管可调用Wrappers不会添加额外的实例成员,因此当你有一个引用10MB内存的Android.Graphics.Bitmap实例时,Xamarin.Android的GC将不知道 - GC会看到一个20字节的对象,将无法确定它是否链接到Android运行时分配的对象,这些对象保持10MB的内存存活.
这表明,不管对象是否被设置为空或不是,你应该还是手动调用Xamarin GC如果你分配/解除分配调用包装,可以潜在地消耗大量的内存.
假设Java Object
是20个字节,如果要分配并且空100个对象每个消耗10MB,则Xamarin GC认为正在使用4000字节的内存.实际上,正在使用~1GB,并且可能会调用GC,也可能不会调用GC.