使用 JQuery 和 Sizzle 的 iframe 内存泄漏

Iframes Memory Leak with JQuery and Sizzle

提问人:vamsi krishna ch 提问时间:6/29/2023 最后编辑:vamsi krishna ch 更新时间:7/2/2023 访问量:82

问:

我们遇到的情况是有 3 个级别的嵌套 iframe。第三个 iframe 初始化了几个大尺寸的对象,但每当用户在应用程序中导航时,这个 iframe 就会被丢弃并在 DOM 中重建。

每当丢弃和构造第 3 级的新 iframe 时,应用程序的堆大小就会不断增加,从而注意到内存泄漏。

用例演示

转到Chrome中的 https://vamsikrishnach90.github.io/。打开开发人员工具(按 F12)并导航到“内存”选项卡。 注意 JS 堆大小,即 arppox 5 MB。

  1. 单击“加载子页面”按钮。子页面加载到父页面的 iframe 中。
  2. 点击子页面上的“轰炸页面”按钮。这将使用一个巨大的虚拟 json 初始化全局变量。打开 devtools 并检查堆,该堆现在为 75 MB。
  3. 单击“删除子页面”按钮。子页面 (iframe) 将从 DOM 中删除。

重复步骤 1 - 3 约 2 次。在步骤 2 之后,记下堆大小。您会注意到,每次我们添加子 iframe 并对其进行轰炸时,堆都会不断增加。尽管在步骤 3 中,我们丢弃了帧,但垃圾回收器不会声明堆。

用例演示帮助(图片)

jquery iframe 泄漏堆内存 嘶嘶作响

评论


答:

0赞 vamsi krishna ch 6/29/2023 #1

重复上述 1-3 个步骤 3 次后,拍摄堆快照。请注意,每次添加子页面并轰炸它时创建的自定义类“Vamsi”的 3 个实例仍然存在于堆中,即使从 DOM 中删除了相应的 iframe。

请注意,在对象图中,已绑定到属于丢弃的 iframe 的 Window 对象。堆内存快照unloadHandler()

根源

子页面在父页面中有一个 jQuery 查找语句:

$('div.msg-banner', window.parent.document).show();

这一行语句导致了内存泄漏问题。

$('div.msg-banner', window.parent.document)

语句的上述部分调用 JQuery find api。这个查找 API 被 Sizzle 覆盖,Sizzle 是 JQuery 采用的纯 JavaScript CSS 选择器引擎。这个来自 JQuery 的查找 api 调用了 Sizzle 的函数 See Picture,该函数将 unloadHandler() 注册到请求的文档的 () 窗口对象中。这导致了父页面的 unload 事件绑定到子页面中的回调函数。因此,即使从 DOM 中删除了子页面 iframe,窗口对象也永远不符合垃圾回收的条件,并且是内存泄漏的原因。setDocumentwindow.parent.documentunloadHandler()

0赞 vamsi krishna ch 6/30/2023 #2

JQuery 论坛上报告的问题 - https://github.com/jquery/jquery/issues/5281