如何在Chrome DevTools堆快照中查找Angular 1.4.7应用的留存共同对象?
如何在Angular 1.4.7中定位未被GC回收的数组内存泄漏
我太懂这种堆快照里Array数量疯涨的头疼了——Angular 1.x的内存泄漏经常藏在层层引用链里,对比视图的默认展示确实没法直接揪出那些跨快照留存的顽固数组。结合我排查Angular老项目的经验,给你几个实用的落地技巧:
1. 用Summary视图的Retainers面板深挖引用链
先在Summary视图里按Constructor分组,找到Array这一项:
- 右键选择Retain Size排序,优先看占内存大的数组(毕竟小数组就算泄漏影响也有限)
- 选中可疑数组后,盯着右侧的Retainers面板——这里会把所有拽着这个数组不让GC回收的对象列得明明白白
- 重点排查Angular相关对象:比如
$scope/$rootScope实例、指令的隔离作用域、单例服务 - 如果看到Detached DOM Tree关联的数组,十有八九是指令销毁时没清理绑定的事件或数据,导致DOM和数组双双被挂住没法回收
- 重点排查Angular相关对象:比如
2. 给Comparison视图加筛选,反向锁定留存数组
你说对比视图只显示新增删除?其实可以换个对比逻辑精准定位:
- 拍三个快照:初始加载完成(Snapshot 1)、完成一轮核心操作(Snapshot 2)、手动触发GC后(Snapshot 3)
- 把Snapshot 3和Snapshot 1做对比,在搜索框输入
Array - 看Size Delta为正的项——这些就是经历了操作和GC,依然赖着不走的数组
- 逐个展开看它们的Retainers,找重复出现的引用源(比如某个全局服务、没销毁的路由控制器)
3. 针对Angular 1.4.x的专属排查点
老版本Angular的泄漏有固定套路,重点查这几个地方:
- 未清理的$watch/$on监听:如果在控制器里给
$rootScope加了监听,或者自定义了$watch,一定要在$destroy事件里解绑:// 错误示范:监听没清理,作用域和数组一直被引用 $rootScope.$on('dataUpdate', () => { $scope.cacheArray.push(newData); }); // 正确写法:在组件销毁时解绑 const unbindListener = $rootScope.$on('dataUpdate', () => { $scope.cacheArray.push(newData); }); $scope.$on('$destroy', unbindListener); - 指令作用域的残留引用:用了
scope: true或隔离作用域的指令,销毁时有没有清空作用域上的数组?比如有些指令会把数组绑定到this或全局对象,忘了在$destroy时置空 - 第三方组件的坑:Angular 1.4.7年代久远,旧版本的UI组件(比如老UI Grid、Datepicker)内部可能有数组泄漏,检查组件销毁时有没有调用官方推荐的清理方法
4. 试试Dominators视图找支配者
切换到Dominators视图,按Constructor分组找Array:
- 这里会显示数组的直接支配者——也就是如果干掉这个对象,数组也会被GC回收。能快速定位到最上层的引用源,比如某个一直存活的单例服务,或者没被销毁的路由控制器
按这个流程走,应该能很快找到那些没被回收的数组的根源。
内容的提问来源于stack exchange,提问作者Rousseau Arulsamy
相关产品推荐
相关产品推荐

