支配者¶
本文介绍了可达性、浅层与保留大小以及支配者的概念,这些概念适用于 JavaScript 等垃圾回收语言。
这些概念在内存分析中很重要,因为对象本身可能很小,但可能持有对其他更大对象的引用,并且通过这样做,将阻止垃圾回收器释放这些额外的内存。
您可以在页面上使用内存工具中的支配者视图查看支配者。
在像 JavaScript 这样的垃圾回收语言中,程序员通常不必担心释放内存。他们可以创建和使用对象,当不再需要对象时,运行时会负责清理并释放对象占用的内存。
可达性¶
在现代 JavaScript 实现中,运行时根据可达性来决定是否不再需要某个对象。在这个系统中,堆表示为一个或多个图。图中的每个节点代表一个对象,节点之间的每个连接(边)代表从一个对象到另一个对象的引用。该图从一个根节点开始,在这些图中用“R”表示。
在垃圾回收期间,运行时从根节点开始遍历图,并标记它找到的每个对象。任何它找不到的对象都是不可达的,可以被释放。
因此,当一个对象变得不可达时(例如,因为它仅被一个超出作用域的单个局部变量引用),那么它引用的任何对象也变得不可达,只要没有其他对象引用它们。
反过来,这意味着只要其他可达对象持有对它们的引用,对象就会保持存活状态。
浅层和保留大小¶
这导致了两种看待对象大小的方式之间的区别
浅层大小:对象本身的大小
保留大小:对象本身的大小,加上由该对象保持存活的其他对象的大小
通常,对象将具有较小的浅层大小,但由于它们包含对其他对象的引用,因此保留大小会大得多。保留大小是分析内存使用情况的重要概念,因为它回答了“如果此对象不再存在,将释放多少内存?”的问题。
支配者¶
一个相关的概念是支配者。如果从根节点到 A 的每条路径都经过 B,则称节点 B 支配节点 A。
如果 A 的任何支配者被释放,则节点 A 本身就会有资格进行垃圾回收。
(如果节点 B 支配节点 A,但不支配 A 的任何其他支配者,则 B 是 A 的直接支配者:)
(这里的一个细微差别是,如果对象 A 被其他两个对象 B 和 C 引用,则这两个对象都不是它的支配者),因为您可以从图中删除 B 或 C,A 仍然会被它的其他引用者保留。相反,A 的直接支配者将是它的第一个共同祖先。