面试题答案
一键面试通过V8堆快照分析工具定位内存泄漏位置
- 抓取堆快照:
- 在Chrome DevTools中,打开应用程序对应的页面,切换到“Memory”面板。
- 先点击“Take snapshot”获取应用程序初始状态的堆快照,记录此时对象的数量和大小等信息。
- 执行一系列可能导致内存泄漏的操作,比如多次重复执行某个功能模块,然后再次点击“Take snapshot”获取操作后的堆快照。
- 对比堆快照:
- 在“Memory”面板中,选择两个堆快照进行对比。展开对象树,查看对象数量和大小的变化。如果某个对象在多次操作后数量持续增加且不应该如此,很可能是内存泄漏点。
- 关注“Retained Size”(保留大小),它表示如果释放该对象,会释放的总内存大小。增长明显且不合理的对象可能是泄漏源。
- 查找那些在操作前后没有被垃圾回收机制回收的对象。例如,某些对象被意外地持有了引用,导致无法被回收。
常见导致内存泄漏的代码模式举例
- 未释放的闭包:
function outerFunction() { const largeArray = new Array(1000000).fill(1); return function innerFunction() { // 这里innerFunction形成闭包,即使outerFunction执行完,largeArray也不会被回收 return largeArray.length; }; } const inner = outerFunction(); // 持续调用inner函数,largeArray一直存在内存中,导致内存泄漏
- 事件监听器未移除:
const eventEmitter = require('events').EventEmitter; const emitter = new EventEmitter(); function listener() { console.log('Event fired'); } emitter.on('event', listener); // 假设这里没有移除监听器,即使emitter不再使用,listener函数也不会被垃圾回收,占用内存
- 缓存使用不当:
const cache = {}; function addToCache(key, value) { cache[key] = value; } function getFromCache(key) { return cache[key]; } // 如果不断向cache添加数据,却没有清理机制,cache会无限增长,导致内存泄漏