关于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实现秒杀时钟倒计时的具体代码,供大家参考,具体内容如下功能介绍:1.时/分/秒倒计时直至为零所有代码
- Python使用for实现无限循环# 方法1.1:借助循环遍历列表的cycle方法from itertools import cyclefo
- 本文实例讲述了jquery判断单选按钮radio是否选中的方法。分享给大家供大家参考。具体如下:html代码如下:<input typ
- 目录简介使用介绍实际体验小结简介MySQL 作为最流行的开源数据库,在各个领域都有相当广泛的应用,作为一个 MySQL DBA,经常会对数据
- Python中try块可以捕获测试代码块中的错误。except块可以处理错误。finally块可以执行代码,而不管try-和except块的
- 传统的机器学习任务从开始到建模的一般流程是:获取数据 -> 数据预处理 -> 训练建模 -> 模型评估 -> 预测,
- MySQL 内连接、左连接、右连接、外连接、多表查询构建环境:create table t_emp(id int primary key,
- String含义:String是一个封装char[]数组的对象,字符串不可变String str = “abc&
- 作者是一名沉迷于Python无法自拔的蛇友,为提高水平,把Python的重点和有趣的实例发在简书上。一、递归是指函数/过程/子程序在运行过程
- 准备工作:python:https://www.python.org/downloads/Dev-C++:https://sourcefor
- 一、管理数据库连接1、使用配置文件管理连接之约定在数据库上下文类中,如果我们只继承了无参数的DbContext,并且在配置文件中创建了和数据
- 读写文件是最常见的IO操作。Python内置了读写文件的函数,用法和C是兼容的。读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由
- 先说明一下为什么要将数组转换成Image类。我处理的图像是FITS (Flexible Image Transport System)文件,
- windows系统下Python环境的搭建step1:下载Python程序 https://www.python.org/downloads
- 由于是通过枚举字典的方式来实现的,因此在开始之前我们需要先构建好密码字典。通过对密码字典挨个进行试错的方式获取正确wifi名称和密码,此内容
- 本文实例讲述了python将ip地址转换成整数的方法。分享给大家供大家参考。具体分析如下:有时候我们用数据库存储ip地址时可以将ip地址转换
- mysql安装启动两种方法如下所示:方法一(简单版):1.cmd进入mysql安装的bin目录:mysqld.exe –install2.n
- 本文实例为大家分享了python图片插入文字的具体代码,供大家参考,具体内容如下问题如何在图片中插入大量文字并且自动换行效果原始图效果图注明
- 删除文件os.remove( filename ) # filename: "要删
- 本方法只做学习研究之用,不得用于商业用途若经济条件允许,请支持并购买正版,链接地址:https://www.jetbrains.com/py