(2)老生代算法
老生代中的对象一般存活时间较长且数量也多,使用了两个算法,分别是标记清除算法和标记压缩算法 。
先来说下什么情况下对象会出现在老生代空间中:
新生代中的对象是否已经经历过一次 Scavenge 算法,如果经历过的话,会将对象从新生代空间移到老生代空间中 。
To 空间的对象占比大小超过 25 % 。在这种情况下,为了不影响到内存分配,会将对象从新生代空间移到老生代空间中 。
老生代中的空间很复杂,有如下几个空间
enum AllocationSpace {
// TODO(v8:7464): Actually map this space's memory as read-only.
RO_SPACE, // 不变的对象空间
NEW_SPACE, // 新生代用于 GC 复制算法的空间
OLD_SPACE, // 老生代常驻对象空间
CODE_SPACE, // 老生代代码对象空间
MAP_SPACE, // 老生代 map 对象
LO_SPACE, // 老生代大空间对象
NEW_LO_SPACE, // 新生代大空间对象
FIRST_SPACE = RO_SPACE,
LAST_SPACE = NEW_LO_SPACE,
FIRST_GROWABLE_PAGED_SPACE = OLD_SPACE,
LAST_GROWABLE_PAGED_SPACE = MAP_SPACE
};
在老生代中,以下情况会先启动标记清除算法:
某一个空间没有分块的时候
空间中被对象超过一定限制
空间不能保证新生代中的对象移动到老生代中
在这个阶段中,会遍历堆中所有的对象,然后标记活的对象,在标记完成后,销毁所有没有被标记的对象 。在标记大型对内存时,可能需要几百毫秒才能完成一次标记 。这就会导致一些性能上的问题 。为了解决这个问题 , 2011 年 , V8 从 stop-the-world 标记切换到增量标志 。在增量标记期间 , GC 将标记工作分解为更小的模块,可以让 JS 应用逻辑在模块间隙执行一会,从而不至于让应用出现停顿情况 。但在 2018 年 , GC 技术又有了一个重大突破 , 这项技术名为并发标记 。该技术可以让 GC 扫描和标记对象时,同时允许 JS 运行 。
清除对象后会造成堆内存出现碎片的情况,当碎片超过一定限制后会启动压缩算法 。在压缩过程中,将活的对象向一端移动,直到所有对象都移动完成然后清理掉不需要的内存 。
2. 哪些操作会造成内存泄漏?
第一种情况是由于使用未声明的变量,而意外的创建了一个全局变量,而使这个变量一直留在内存中无法被回收 。
第二种情况是设置了 setInterval 定时器 , 而忘记取消它,如果循环函数有对外部变量的引用的话,那么这个变量会被一直留在内存中,而无法被回收 。
第三种情况是获取一个 DOM 元素的引用,而后面这个元素被删除 , 由于我们一直保留了对这个元素的引用,所以它也无法被回收 。
【浏览器原理面试题 前端「前端面试进阶之浏览器原理」】第四种情况是不合理的使用闭包,从而导致某些变量一直被留在内存当中 。
- 筑基金丹元婴类修真小说推荐 讲里面有金丹元婴境界是哪部
- 面对非正义行为我们应该怎么做
- 九月份种植的蔬菜有哪些?
- 天涯何处无芳草.何必单恋一枝花 天涯何处无芳草何必单恋一枝花后面怎么说
- 美白面膜用多了会怎么样 美白面膜能天天敷吗?
- 水猴子图片真实图片 水鬼 水里面真的有水猴子存在吗
- 抖音里面最火28首歌 看看你喜爱的歌曲上榜了吗
- 京东帮人下单「京东给别人代下单骗局大揭秘解开神秘面纱」
- 早餐面粉的做法大全 用面粉做早餐有哪些做法
- 口才不好看什么书管用