夜下客

繁体版 简体版
夜下客 > JS修炼法则 > 第23章 V8从JS追踪DOM并返回

第23章 V8从JS追踪DOM并返回

一.前言

在当前的 Chrome 中,追踪内存泄漏较为容易。

Chrome DevTools 的Memory功能 可以对C++DOM对象 进行追踪和快照,并显示 JS 中所有可访问的 DOM对象及其引用。

当未使用对象由于其他对象的引用未释放时,就发生了垃圾回收系统中的内存泄漏。

前端的内存泄漏通常涉及 JS对象 和 DOM元素 的交互。

如下代码。开发者忘记移除事件监听器而导致内存泄漏。事件监听器引用的所有对象都不能被垃圾回收,同时 iframe 和 事件监听器 一起泄漏。并且泄漏的 iframe 使得它的所有对象均泄漏。

// Main window:

const iframe = document.createElement('iframe');

iframe.src = 'iframe.html';

document.body.appendChild(iframe);

iframe.addEventListener('load', function() {

const localVariable = iframe.contentWindow;

function leakingListener() {

// Do something with `localVariable`.

if (localVariable) {}

document.body.addEventListener('my-debug-event', leakingListener);

document.body.removeChild(iframe);

// BUG: forgot to unregister `leakingListener`.

});

// iframe.html:

class Leak {};

window.globalVariable = new Leak();

学习保留路径的概念有助于找到内存泄漏。

保留路径是一条对象链,每个对象都是阻止垃圾回收的泄漏对象。它从一个根对象开始,通常是window全局对象,在泄漏对象处结束。

链中的每个中间对象,都有对链中下一个对象的直接引用。

例如,iframe 中 Leak对象 的保留路径如下:

保留路径两次跨越 JavaScript / DOM 边界(分别以绿色/红色显示)。

JavaScript 对象存在于 V8 堆中,而 DOM 对象是 Chrome 中的 C++ 对象。

你可以访问一个线上实例,去查看堆快照中的内存泄漏 线上 iframe 内存泄漏

二.DevTools堆快照

可通过在 DevTools 中堆快照来检查任何对象的保留路径。堆快照精确地捕获了 V8 堆上的所有对象。

DevTools 通过 C++ DOM 对象进行跟踪,并精确地捕获 JS对象 和 C++ DOM 之间的引用。

第一行说明:该Leak对象存储于 iframe 中 window 对象的 global_variable 。

三.底层:跨组件追踪

DOM 对象由 Blink 管理。Blink是Chrome 的渲染引擎,它负责将 DOM 转换为屏幕上的实际文本和图像。

Blink 和它对 DOM 的表示是用 C++ 编写的,这意味着 DOM 不能直接暴露给 JS。

DOM 中的对象分为两部分:JS 可用的 V8 包装器对象和表示 DOM 中节点的 C++ 对象。这些对象之间彼此引用。

跨组件追踪是一种通过从 JS 跟踪到 C++ 实现的DOM ,并返回来确定对象活跃度的机制。

『加入书签,方便阅读』