本文介绍了在内存不足之前,GC 不应该在 Xamarin.Android 中自动运行吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我几乎花了一整天的时间试图找出 Android 内存泄漏的原因.有一个活动我多次打开/关闭(带计时器).过了一会儿,我收到了 OutOfMemory 错误:

I spent almost a whole day trying to find out the reason of a memory leak in Android. There´s an activity that I open/close many many times (with a timer). After a while I was getting OutOfMemory errors:

每次打开活动时,我都看到 Xamarin Profiler 中的内存不断增加:

I saw the memory going up constantly in Xamarin Profiler every time the activity opened:

我确保没有可能卡在该活动中的属性或事件处理程序.我什至删除了每个图像、按钮等,试图检测导致内存泄漏的原因.还是一样...

I made sure there were no properties or event handlers that could be stuck in that activity. I even removed every image, buttons, etc, trying to detect what was causing the memory leak. Still the same...

然后我在主要活动(打开有问题活动的那个)的 OnResume 方法中做了 GC.Collect().现在我可以看到内存按原样上下波动.您可以在屏幕截图中看到结果:

Then I did GC.Collect() in the OnResume method of main activity (the one that opens the problematic activity). Now I can see the memory going up and down as it should. You can see the result in the screenshot:

根据 Xamarin 文档:

当次要堆的内存不足以供新分配时,GC 将运行

但事实并非如此

推荐答案

您可能希望在 Helping the GC 下的链接中进一步阅读:GC 有一个不完整的进程视图,当内存不足时可能无法运行,因为 GC 不知道内存不足.Managed Callable Wrappers 不添加额外的实例成员

You may want to read a bit further down in your link under Helping the 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. andManaged Callable Wrappers do not add additional instance members

基本上,看起来 BaseActivity 是一个 Android Callable Wrapper (ACW),Mono GC 不知道它有多大,所以它不知道调用垃圾收集器.据我所知,ACW 是实现 Android 界面的一种方式.

Basically, it would appear BaseActivity is an Android Callable Wrapper (ACW) and the Mono GC doesn't know how big it is, so it doesn't know to invoke the garbage collector. From what I gather, the ACW is a way to implement Android interfaces.

正如您所发现的,解决方案是在使用 ACW 时手动调用 Xamarin 文档中推荐的垃圾收集器.

The solution is, as you discovered, to manually call the garbage collector which is recommended in the Xamarin docs when using ACW's.

http://developer.xamarin.com/guides/android/advanced_topics/垃圾收集/

----

自从最初发布此答案以来,Xamarin 文档已改进了对这种情况的解释:

Since the original posting of this answer, the Xamarin docs have improved in their explanation of this situation:

Java.Lang.Object 类型或派生类型的实例是大小至少为 20 字节.托管可调用包装器不添加额外的实例成员,所以当你有一个 Android.Graphics.Bitmap 实例时指的是 10MB 的内存块,Xamarin.Android 的 GC 不会知道– GC 将看到一个 20 字节的对象并且无法确定它链接到保留的 Android 运行时分配的对象10MB 内存可用.

这表明,无论对象是否设置为 null,如果您正在分配/取消分配可调用包装器,您应该仍然手动调用 Xamarin GC可能会消耗大量内存.

This indicates that, regardless of whether objects are set to null or not, you should still manually call the Xamarin GC if you're allocating/deallocating Callable Wrappers that can potentially consume a large amount of memory.

在假设 Java Object 为 20 字节的情况下操作,如果要分配 100 个对象并将其设为 null,每个对象消耗 10MB,Xamarin GC 认为有 4000 字节的内存正在使用中.实际上,大约 1GB 正在使用中,并且可能会或可能不会调用 GC.

Operating under the assumption a Java Object is 20 bytes, if one were to allocate and null 100 objects that consume 10MB each, the Xamarin GC believes that 4000 bytes of memory are in use. In reality, ~1GB is in use, and the GC may or may not be invoked.

这篇关于在内存不足之前,GC 不应该在 Xamarin.Android 中自动运行吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-30 23:21