关于Javascript的内存泄漏问题

作者:海啸 来源:海啸博客 时间:2008-04-15 07:46:00 

常规循环引用内存泄漏和Closure内存泄漏

要了解javascript的内存泄漏问题,首先要了解的就是javascript的GC原理。

我记得原来在犀牛书《JavaScript: The Definitive Guide》中看到过,IE使用的GC算法是计数器,因此只碰到循环 引用就会造成memory leakage。后来一直觉得和观察到的现象很不一致,直到看到Eric的文章,才明白犀牛书的说法没有说得很明确,估计该书成文后IE升级过算法吧。在IE 6中,对于javascript object内部,jscript使用的是mark-and-sweep算法,而对于javascript object与外部object(包括native object和vbscript object等等)的引用时,IE 6使用的才是计数器的算法。

Eric Lippert在http://blogs.msdn.com/ericlippert/archive/2003/09/17/53038.aspx一文中提到IE 6中JScript的GC算法使用的是nongeneration mark-and-sweep。对于javascript对算法的实现缺陷,文章如是说:

"The benefits of this approach are numerous, but the principle benefit is that circular references are not leaked unless the circular reference involves an object not owned by JScript. "

也就是说,IE 6对于纯粹的Script Objects间的Circular References是可以正确处理的,可惜它处理不了的是JScript与Native Object(例如Dom、ActiveX Object)之间的Circular References。

所以,当我们出现Native对象(例如Dom、ActiveX Object)与Javascript对象间的循环引用时,内存泄露的问题就出现了。当然,这个bug在IE 7中已经被修复了[http://www.quirksmode.org/blog/archives/2006/04/ie_7_and_javasc.html]。

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp 中有个示意图和简单的例子体现了这个问题:

<html>
<head>
<script language = " JScript ">
var myGlobalObject;
function  SetupLeak()  // 产生循环引用,因此会造成内存泄露
{
    //  First set up the script scope to element reference
    myGlobalObject  = document.getElementById("LeakedDiv");
    //  Next set up the element to script scope reference
    document.getElementById(" LeakedDiv ").expandoProperty  = myGlobalObject;
}
function  BreakLeak()  // 解开循环引用,解决内存泄露问题
{
    document.getElementById( " LeakedDiv " ).expandoProperty  = null ;
}
</script>
</head>
<body onload = "SetupLeak()"  onunload = "BreakLeak()">
<div id = "LeakedDiv" ></div>
</body>
</html>

   

上面这个例子,看似很简单就能够解决内存泄露的问题。可惜的是,当我们的代码中的结构复杂了以后,造成循环引用的原因开始变得多样,我们就没法那么容易观察到了,这时候,我们必须对代码进行仔细的检查。

尤其是当碰到Closure,当我们往Native对象(例如Dom对象、ActiveX Object)上绑定事件响应代码时,一个不小心,我们就会制造出Closure Memory Leak。其关键原因,其实和前者是一样的,也是一个跨javascript object和native object的循环引用。只是代码更为隐蔽,这个隐蔽性,是由于javascript的语言特性造成的。但在使用类似内嵌函数的时候,内嵌的函数有拥有一个reference指向外部函数的scope,包括外部函数的参数,因此也就很容易造成一个很隐蔽的循环引用,例如:

DOM_Node.onevent ->function_object.[ [ scope ] ] ->scope_chain ->Activation_object.nodeRef ->DOM_Node。

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp]有个例子极深刻地显示了该隐蔽性:

<html>
<head>
<script language = "JScript">
function  AttachEvents(element)
{
    //  This structure causes element to ref ClickEventHandler
    //  element有个引用指向函数ClickEventHandler()
    element.attachEvent("onclick", ClickEventHandler);
    function  ClickEventHandler(){
                 //  This closure refs element
                 //  该函数有个引用指向AttachEvents(element)调用Scope,也就是执行了参数element。
    }
}
function  SetupLeak()
{
    //  The leak happens all at once
    AttachEvents(document.getElementById("LeakedDiv"));
}
</script>
</head>
<body onload = "SetupLeak()"  onunload = "BreakLeak()">
<div id = "LeakedDiv"></div>
</body>
</html>

标签:内存,泄露,javascript
0
投稿

猜你喜欢

  • 关于DOM元素定位属性的深入学习

    2008-04-02 11:46:00
  • 服务器响应HTTP的类型ContentType大全

    2007-10-23 10:21:00
  • Oracle 添加用户并赋权,修改密码,解锁,删除用户的方法

    2009-10-14 11:37:00
  • HTML5本地存储初探(一)

    2010-03-07 15:42:00
  • CSS中的标点符号用法

    2008-10-03 11:58:00
  • asp什么情况下用响应缓冲会提高运行速度?

    2010-07-14 21:02:00
  • Oracle中Union与Union All的区别(适用多个数据库)

    2012-07-21 15:13:27
  • 剖析网页设计中的几何圆

    2010-10-19 12:27:00
  • Mootools 1.2教程(14)——定时器和哈希简介

    2008-12-08 12:50:00
  • QQ聊天窗口链接提示效果代码

    2008-12-16 12:59:00
  • IE不支持border-spacing的解决办法

    2009-04-28 13:11:00
  • 2008年Logo设计10大趋势

    2008-02-28 13:06:00
  • “Unable to read local eventlog (reason:事件日志文件已在读取时间更改)”解决办法

    2009-08-27 13:12:00
  • 用户体验与心流理论

    2008-09-23 11:51:00
  • WEB3.0时代的开放与聚合

    2008-08-21 17:19:00
  • ACCESS入门教程:窗口和菜单的使用

    2008-01-03 20:15:00
  • 用ASP显示ACCESS数据库的的GIF图象

    2008-11-20 16:35:00
  • Javascript DOM 编程实例讲解--仿LightBox效果提示框

    2008-05-01 13:25:00
  • 在不能中寻找可能 QZONE个性相册设计的始末

    2009-07-13 12:27:00
  • Google谷歌的CSS前景图片合并技术

    2009-07-13 12:21:00
  • asp之家 网络编程 m.aspxhome.com