浏览器的垃圾回收机制与内存泄露

182 阅读2分钟

一. 垃圾回收

浏览器常用的垃圾回收机制有两种:标记清除分代垃圾回收引用计数【几乎已经废弃,很少浏览器进行使用了】

JavaScript解释器可以检测到何时程序不再使用一个对象了,当它确定这个对象是无用的时候,他就知道不再需要这个对象了,就可以把它占用的内存释放掉了。

1. 标记清除【三色标记法】

JavaScript中有一个全局对象,定期的,垃圾回收器将从这个全局对象开始,找出所有从这个全局对象开始引用的对象,再找这些对象引用的对象...对这些活跃的对象标记,这是标记阶段。清除阶段就是清除那些没有被标记的对象。

问题: 在清除过后,内存空间会变得不连续,即会出现内存碎片。

解决: 采用 标记整理 ,区别于标记清除,只是标记结束后,标记整理法会将存活的对象向内存的一边移动,最后清理掉边界内存。

2. 分代垃圾回收

Chrome 使用分代垃圾回收机制,将内存分为新生代老生代两个代。新生代包含经常创建和短暂存在的对象,垃圾回收频率较高;而老生代包含存活时间较长的对象,垃圾回收频率较低。新生代使用的是更轻量级的回收算法(如Scavenge算法),而老生代使用的则是更复杂的回收算法(如Mark-Sweep、Mark-Compact等)。

二. 内存泄漏

内存泄漏(Memory Leak) 是指在程序中使用动态内存分配(例如 malloc、new 等)时,由于某些原因没有释放已分配的内存,导致可用内存减少,最终导致程序运行效率下降、甚至崩溃的现象。

内存泄漏的原因:

  • 对象创建后没有及时释放:程序中创建了对象,但是没有及时释放对象所占的内存,使得对象所占的内存一直处于占用状态,最终导致内存不足。

  • 代码无法访问到某些对象,导致无法释放:在程序中,运行时可能产生某些已经无法访问到的对象(例如因为没有正确的指针引用),这些对象的内存也无法被释放。

  • 循环引用:在程序中,可能会出现对象之间形成的循环引用关系,使得这些对象的引用计数始终不为 0,导致这些对象的内存不能被正确的释放。

避免内存泄漏的一些方法:

  • 避免循环引用
  • 重复利用对象,可采用对象池对对象进行管理!