• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

android - Xamarin Android 垃圾回收算法

[复制链接]
菜鸟教程小白 发表于 2022-12-9 03:01:06 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我正在阅读 Xamarin.Android 垃圾收集文档,了解 reducing referenced instances 帮助 GC 更好地执行。 .

该部分开头说:

Whenever an instance of a Java.Lang.Object type or subclass is scanned during the GC, the entire object graph that the instance refers to must also be scanned. The object graph is the set of object instances that the "root instance" refers to, plus everything referenced by what the root instance refers to, recursively.

...我明白了。

然后它会显示一个继承自标准 Activity 类的自定义类。这个自定义 Activity 类有一个字段,它是一个字符串列表,在构造函数中初始化为具有 10,000 个字符串。据说这很糟糕,因为在 GC 期间必须扫描所有 10,000 个实例的可达性。我也明白。

我不清楚的部分是推荐的修复:它说 List 字段应该移动到另一个不继承自 Java.Lang 的类.Object 然后应该从 Activity 中引用该类的实例,就像之前引用列表一样。

我的问题:当实例总数仍然是 10,000 并且开头段落说由于过程是递归的而最终将被扫描时,将字段更深地插入对象图中如何帮助 GC?

作为旁注,我还在阅读 (here ) 关于 Mono 在 Android 上使用的 SGen GC,并且对象图遍历过程被描述为从 GC 根开始的广度优先。这解释了一个包含 10,000 个项目的列表将如何在检查每个项目时导致更长的 GC 暂停,但仍然没有解释将该列表移入图表的更深处会有什么帮助,因为 GC 最终会在它深入图表时对其进行扫描。



Best Answer-推荐答案


我会尽力解释这一点,我远不是专家,所以任何想插话的人,请这样做。

当我们提到进行 peer walk 时,我们是在定位任何 roots 并遍历实时引用图以查看哪些是可达的,哪些不是: p>

enter image description here

根对象:

  • 静态字段/属性指向的对象
  • 每个托管线程的堆栈上的对象
  • 已传递到 native API 的对象

基本上,您必须处理两个托管 GC。我们将它们称为 Xamarin GC 和 Android GC 以供引用。

enter image description here

Xamarin.Android 具有 peer objects,用于引用 Android JVM 中已知的 native Java 对象。他们实现了一个核心接口(interface):

namespace Android.Runtime
{
    public interface IJavaObject : IDisposable
    {
        // JNI reference to the Java object it is wrapping. 
        // Also known as a pointer to the JVM object
        public IntPtr Handle { get; set; }
        ...
    }
}

只要我们有一个继承了 IJavaObject 的对象,它将通过上面的 JNI 句柄保持强引用,以确保只要托管对象还活着,它就一直保持活跃。

这样想:

IJavaObject -> IntPtr Handle -> Java Object

用 GC 术语表示如下:

Xamarin GC 分配和收集 -> GC Root -> Android GC 分配和收集

然后我们在 Xamarin.Android 中有一个 GC 进程:

enter image description here

当 GC 运行时,您可以看到它将用弱引用替换强 JNI 句柄,然后调用将收集我们的 Java 对象的 Android GC。因此,会扫描 peers 中的任何关系,以确保它们在 JVM 中被镜像。这样可以防止这些对象被过早收集。

一旦发生这种情况,我们就会运行 Android GC,完成后它将遍历对等对象并检查弱引用。

  • 如果一个对象消失了,我们会在 C# 端收集它
  • 如果对象仍然存在,那么我们将弱引用改回强 JNI 句柄

因此,每次 GC 在 peer 对象上运行时,都需要检查和更新此图。这就是为什么这些包装器类型对象要慢得多的原因,因为必须从对等对象开始扫描整个对象图。

因此,当我们的 peer 对象使用重要的对象图时,我们可以通过将引用的存储移动到 peer 类之外来帮助 GC 过程。这通常通过 rooting 独立于对等方的引用来完成。而且由于它没有存储为字段,GC 不会尝试在对象图上进行关系遍历。

如前所述,在您注意到长 GC 之前,这不是一个需要担心的大问题。然后,您可以将其用作解决方案。

图片来源:Xamarin 大学(https://www.xamarin.com/university)

关于android - Xamarin Android 垃圾回收算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39066640/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap