在N久以前,js开始在国内盛行的时候,Web开发人员并没有太多的去关注内存泄露问题。主要是

那时的页面间联系大都比较简单,并主要使用不同的连接地址在同一个站点中导航,这样的设计方

式是非常有利于浏览器释放资源的。即使Web页面运行中真的出现了资源泄漏,那它的影响也是非常

有限而且常常是不会被人在意的。

    然而今天人们对Web应用有了高更的要求。一个页面很可能数小时不会发生URL跳转,并同时通

过Web服务动态的更新页面内容。复杂的事件关联设计、基于对象的JScript和DHTML技术的广泛采用

,使得代码的能力达到了其承受的极限。在这样的情况和改变下,弄清楚内存泄露方式变得非常的

急迫,特别是过去这些问题都被传统的页面导航方法给屏蔽了。

    还算好的事情是,当你明确了希望寻找什么时,内存泄露方式是比较容易被确定的。大多数你

能遇到的泄露问题我们都已经知道,你只需要少量额外的工作就会给你带来好处。虽然在一些页面

中少量的小泄漏问题仍会发生,但是主要的问题还是很容易解决的。


1.什么是内存泄露?

内存泄露是指分配给应用的内存不能被重新分配,即使在内存已经不被使用的时候。正常情况下,

垃圾回收器在DOM元素和event处理器不被引用或访问的时候回收它们。但是,IE的早些版本(IE7和

之前)中内存泄露是很容易出现的,因为内存管理器不能正确理解Javascript生命周期而且在周期

被打破(可以通过赋值为null实现)前不会回收内存。


2.为什么你需要注意它?

    在大型Web应用程序中内存泄露是一种常见的意外编程错误。内存泄露会降低Web应用程序的性能,

直到浪费的内存超过了系统所能分配的,应用程序将不能使用。作为一Web开发者,开发一个满足功

能要求的应用程序只是第一步,性能要求和Web应用程序的成功是同样重要的,更何况它可能会导致

应用程序错误或浏览器崩溃。


3.Javascript中出现内存泄露的主要原因?


1)    循环引用

    举一个很简单的例子:一个DOM对象被一个Javascript对象引用,与此同时又引用同一个或其它的

Javascript对象,这个DOM对象可能会引发内存泄露。这个DOM对象的引用将不会在脚本停止的时候

被垃圾回收器回收。要想破坏循环引用,引用DOM元素的对象或DOM对象的引用需要被赋值为null。


2)    Javascript闭包

    因为Javascript范围的限制,许多实现依赖Javascript不包,闭包可以导致内存泄露是因为内部函数保持一个对外部函数变量的引用,所以尽管函数返回了内部函数还可以继续访问在外部方法中定义的私有变量。对Javascript程序员来说最好的做法是在页面重载前断开所有的事件处理器。


3)DOM插入顺序

    当2个不同范围的 DOM 对象连添加到一起的时候一个临时的对象会被创建。这个DOM对象改变范围到

document时,那个临时对象就没用了。也就是说, DOM 对象应该按照从当前页面存在的最上面的 

DOM 元素开始往下直到剩下的 DOM 元素的顺序添加,这样它们就总是有同样的范围,不会产生临时

对象。

4)    页面交叉泄漏(Cross-Page Leaks) 

    页面交叉泄漏其实是一种较小的泄漏,它通常在你浏览过程中,由于内部对象薄计引起。下面我们会讨论DOM插入顺序的问题,在那个示例中你会发现只需要改动少量的代码,我们就可以避免对象薄计对对象构建带来的影响;


5)    貌似泄漏(Pseudo-Leaks) 

    这个不是真正的意义上的泄漏,不过如果你不了解它,你可能会在你的可用内存资源变得越来越少的时候极度郁闷。为了演示这个问题,我们将通过重写Script元素中的内容来引发大量内存的"泄漏"。


4)如何检测?


    内存泄露对开发者来说一般很难检测因为它们是由一些大量代码中的意外的错误引起的,但它在系

统内存不足前并不影响程序的功能。这就是为什么会有人在很长时间的测试期中收集应用程序性能

指标来测试性能。

    下面介绍几种内存泄露的检测工具。

1.Chrome开发者工具。

js内存泄露简介_js


2.Drip/sIEve

Drip和sIEve的作者应该是同一个人,连open souce上的项目都是在一起的。不过,平时我们主要使用sIEve就可以了,sIEve的功能比Drip强大一些 

js内存泄露简介_js_02 
sIEve 界面很简单,左侧:内嵌了一个浏览器控件,我可以访问任何网址,下方还有个内存检查,这样我们可以方便看出内存的升降情况以及dom使用数量曲线。

右侧面板,我们可以通过 Show in use 看到目前页面使用的dom的情况,Show Leaks 可以看到内存泄露的dom。当然每次显示泄露的情况必须是页面刷新后,看到上一个页面的泄露情况。

同时通过右侧的数据颜色,我们可以看到内存的升降和具体的数量级

js内存泄露简介_内存泄露_03
不过sIEve的工作原理是对所有dom进行了一次hack,然后自己判断那些dom没有被释放掉,但是具体的情况比较难分析出来。而且跟踪有问题的dom需要一定技巧,对于大型的应用程序,跟踪难度大。

 不过用来检测小模块的内存使用情况还是一个不错的选择,特别是大项目模块细分后,对每个模块的单独测试还是比较不错的 
 谢谢怿飞同学提示的下载地址, Drip/sIEve下载地址:
http://home.orange.nl/jsrosman/

3. Javascript Leaks Detector

这是来自微软GPDE团队的一个小工具,下面简称JLD

官网: http://blogs.msdn.com/gpde/pages/javascript-memory-leak-detector.aspx

安装后,我们可以在ie浏览器的 查看->浏览器栏中找到

 js内存泄露简介_js_04
 JLD强大之处在于能够模拟IE6和IE7的GC情况,和真实的回收情况。这样可以做一个比较。

  js内存泄露简介_内存泄露_05

这里通常能只能反应IE6和IE7的理想情况,我们需要选择下面Actual Leaks来反映当前浏览器的真实情况。

 

浏览器刷新后,我们就可以看到上次页面的结果了,绿色代表没有发现内存泄露,红色代表发现了内存泄露,蓝色是当前加载完成的页面,当然还有黑色,是指正在加载的网页

当我们展开一个有问题的页面时,

 js内存泄露简介_内存泄露_06
我们可以看到一个有问题分支Leaks.这里列出了有问题的节点,同时还能帮我们列出出现问题的脚本在什么地方。

这点非常方便我们定位出泄露的问题所在。不过要使用脚本调试,我们必须要打开ie的脚本调试功能

 js内存泄露简介_js_07
在ie选项的高级中,我们去掉这两个勾即可

4. Leak Monitor

这是firefox上唯一一个检查内存泄露的工具,不过这里舜子不太推荐使用。因为firefox的内存GC机制比IE强悍,不必作为重点考虑对象。只要ie的问题能处理好,firefox上基本上也没有什么问题。而且有ie这两个强悍的软件帮忙基本上能解决大部分问题了。

 js内存泄露简介_内存泄露_08

 可惜这个工具的体验很糟糕,会让人很有一种抓狂的感觉。如果您还要继续尝试可以到这里下载: https://addons.mozilla.org/zh-CN/firefox/addon/2490


好了,就介绍到这,下面几篇博客将详细介绍,内存泄露的相关细节知识。

参考博客:

http://my.oschina.net/tsl0922/blog/56038

http://lanhy2000.blog.163.com/blog/static/43678608201121472644851/

http://www.cnblogs.com/jenry/archive/2011/02/23/1961844.html

http://www.cnblogs.com/rainman/archive/2009/03/07/1405624.html