魔鬼的梦魇—验证IE中的js内存泄露模式(续)
2012-05-16 00:08
211 查看
魔鬼的梦魇—验证IE中的js内存泄露模式(续)
前面几篇文章我们验证学习了Justin Rogers文章中提出的集中泄露模式,但是其中并没有介绍Iframe的内存泄露情况;其中的各种原因,我觉的虽然当时ajax的兴起,极大地促进了web应用程序的开发和发展,但是并没有涉及到大规模的动态更新页面DOM元素,所以这个时候的泄露都不至于会引起大家的关注;但是随着大量js类库框架的出现,特别是extjs的出现,功能丰富界面漂亮美观,同时提供了大量丰富的前端控件,顿时使人眼前一亮,很多人都会不由的感到震撼,原来bs也可以做出这么优美酷炫的界面;特别是最近移动互联网的风行,很多复杂的应用都转移到了前段,这些复杂的应用基本上展现基本上都会涉及到动态创建DOM,同时很多应用也会使用iframe,这就会导致内存泄露的滋生;如果你的应用足够复杂,那么泄露的情况也会十分严重,甚至导致浏览器崩溃。
我们先来看一下“史前时代”,使用iframe是否存在内存泄露,泄露的情况如何?我们新建一个普通的静态html页面;然后我们在一个包含iframe的页面中,通过点击按钮不断的刷新iframe,具体代码如下
iframe嵌套的静态html页面
[html] view plaincopy
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
UnLeakIFrameContent
</body>
</html>
包含iframe的页面
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
var IFrameLeakTester = {
frameTagId: "frame"
,
staticDOMUrl: "UnLeakIFrameContent.htm"
,
staticLeak: function () {
var frame = document.getElementById(this.frameTagId);
frame.src = this.staticDOMUrl;
}
};
</script>
</head>
<body>
<div>
<input type="button" value = "staticDOMLeak" onclick="IFrameLeakTester.staticLeak();" />
</div>
<div>
<iframe id="frame" src="UnLeakIFrameContent.htm" height = "500px" width = "100%">
</iframe>
</div>
</body>
</html>
从代码中,我们可以看到没有任何的循环引用和动态的DOM创建,自然我们刷新整个包含iframe的页面也不会有内存泄露,使用sIEve测试也证明了这一点。
![](http://my.csdn.net/uploads/201205/15/1337097511_5021.png)
图 1. 刷新iframe中嵌套静态网页内存泄露情况
如果我们不断的点击页面中的按钮,来不断的刷新iframe,这个时候是否有内存泄露呢?从下图的测试数据来看,我们看到泄露的确是存在的,只是泄露的数目并没有随刷新的次数递增,所以我猜想是IE缓存了iframe的页面对象的DOM。
![](http://my.csdn.net/uploads/201205/15/1337097538_8342.png)
图 2. Iframe嵌套静态页面,不断刷新iframe的内存泄露情况
那么如果iframe嵌套的页面有动态创建DOM的逻辑的话,那泄露的情况会怎样呢?这次嵌套的页面我们使用extjs中的那个模仿windows桌面的页面(examples/desktop/desktop.html),我们先来看一下这个页面本身是否有泄露问题,从图3中,我们可以看到是没有泄露问题的。
![](http://my.csdn.net/uploads/201205/15/1337097559_2661.png)
图 3. 直接刷新extjs的desktop例子泄露情况
接下来我们将iframe的嵌套页面改成extjs的desktop.html,通过同样的方式,我们看一下刷新整个页面和不断刷新iframe时,来看一下内存泄露的具体情况;详细代码如下
包含iframe的页面
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
var IFrameLeakTester = {
frameTagId: "frame"
,
dynamicDOMUrl: "http://localhost:30000/examples/desktop/desktop.html"
,
leak: function () {
this._leak(true);
}
,
unLeak: function () {
this._leak(false);
}
,
_leak: function (leak) {
var frame = document.getElementById(this.frameTagId);
//网上流传的方法,但是在这种情况下没有什么效果
if (!leak) {
this.clear(frame);
}
frame.src = this.dynamicDOMUrl;
}
,
clear: function (frame) {
if (frame) {
frame.contentWindow.document.write("");
frame.contentWindow.document.clear();
top.CollectGarbage();
}
}
};
</script>
</head>
<body>
<div>
<input type="button" value="dynamicDOMLeak" onclick="IFrameLeakTester.leak();"/>
<input type="button" value = "dynamicDOMUnLeak" onclick="IFrameLeakTester.unLeak();" />
</div>
<div>
<iframe id="frame" src="UnLeakIFrameContent.htm" height = "500px" width = "100%">
</iframe>
</div>
</body>
</html>
![](http://my.csdn.net/uploads/201205/15/1337097591_8719.png)
图 4. 刷新嵌套extjs例子的这个页面内存泄露情况
![](http://my.csdn.net/uploads/201205/16/1337097610_3620.png)
图 5. 不断刷新嵌套extjs例子的iframe内存泄露情况
从图4和图5中,我们可以看到刷新整个页面也是没有泄露的,但是刷新iframe却存在泄露,并且刷新的次数越多泄露越严重。综合前面iframe嵌套静态页面的例子,我们可以知道,IE可以缓存页面本身的DOM,以备再次刷新iframe的同一页面的时候用;但是如果iframe嵌套的页面中新建了DOM元素,那么每次打开这个页面的时候都会新建对应的DOM元素,从而导致严重的内存泄露。
对于怎样应对这种内存泄露的情况,我没有发现行之有效的方法;在网上搜到一些解决的方法,但是我测试了一下(单击dynamicDOMUnLeak按钮),没有什么效果,具体情况如下图
![](http://my.csdn.net/uploads/201205/16/1337097629_2798.png)
图 6. 解决泄露的代码没有效果
前面几篇文章我们验证学习了Justin Rogers文章中提出的集中泄露模式,但是其中并没有介绍Iframe的内存泄露情况;其中的各种原因,我觉的虽然当时ajax的兴起,极大地促进了web应用程序的开发和发展,但是并没有涉及到大规模的动态更新页面DOM元素,所以这个时候的泄露都不至于会引起大家的关注;但是随着大量js类库框架的出现,特别是extjs的出现,功能丰富界面漂亮美观,同时提供了大量丰富的前端控件,顿时使人眼前一亮,很多人都会不由的感到震撼,原来bs也可以做出这么优美酷炫的界面;特别是最近移动互联网的风行,很多复杂的应用都转移到了前段,这些复杂的应用基本上展现基本上都会涉及到动态创建DOM,同时很多应用也会使用iframe,这就会导致内存泄露的滋生;如果你的应用足够复杂,那么泄露的情况也会十分严重,甚至导致浏览器崩溃。
我们先来看一下“史前时代”,使用iframe是否存在内存泄露,泄露的情况如何?我们新建一个普通的静态html页面;然后我们在一个包含iframe的页面中,通过点击按钮不断的刷新iframe,具体代码如下
iframe嵌套的静态html页面
[html] view plaincopy
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
UnLeakIFrameContent
</body>
</html>
包含iframe的页面
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
var IFrameLeakTester = {
frameTagId: "frame"
,
staticDOMUrl: "UnLeakIFrameContent.htm"
,
staticLeak: function () {
var frame = document.getElementById(this.frameTagId);
frame.src = this.staticDOMUrl;
}
};
</script>
</head>
<body>
<div>
<input type="button" value = "staticDOMLeak" onclick="IFrameLeakTester.staticLeak();" />
</div>
<div>
<iframe id="frame" src="UnLeakIFrameContent.htm" height = "500px" width = "100%">
</iframe>
</div>
</body>
</html>
从代码中,我们可以看到没有任何的循环引用和动态的DOM创建,自然我们刷新整个包含iframe的页面也不会有内存泄露,使用sIEve测试也证明了这一点。
![](http://my.csdn.net/uploads/201205/15/1337097511_5021.png)
图 1. 刷新iframe中嵌套静态网页内存泄露情况
如果我们不断的点击页面中的按钮,来不断的刷新iframe,这个时候是否有内存泄露呢?从下图的测试数据来看,我们看到泄露的确是存在的,只是泄露的数目并没有随刷新的次数递增,所以我猜想是IE缓存了iframe的页面对象的DOM。
![](http://my.csdn.net/uploads/201205/15/1337097538_8342.png)
图 2. Iframe嵌套静态页面,不断刷新iframe的内存泄露情况
那么如果iframe嵌套的页面有动态创建DOM的逻辑的话,那泄露的情况会怎样呢?这次嵌套的页面我们使用extjs中的那个模仿windows桌面的页面(examples/desktop/desktop.html),我们先来看一下这个页面本身是否有泄露问题,从图3中,我们可以看到是没有泄露问题的。
![](http://my.csdn.net/uploads/201205/15/1337097559_2661.png)
图 3. 直接刷新extjs的desktop例子泄露情况
接下来我们将iframe的嵌套页面改成extjs的desktop.html,通过同样的方式,我们看一下刷新整个页面和不断刷新iframe时,来看一下内存泄露的具体情况;详细代码如下
包含iframe的页面
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
var IFrameLeakTester = {
frameTagId: "frame"
,
dynamicDOMUrl: "http://localhost:30000/examples/desktop/desktop.html"
,
leak: function () {
this._leak(true);
}
,
unLeak: function () {
this._leak(false);
}
,
_leak: function (leak) {
var frame = document.getElementById(this.frameTagId);
//网上流传的方法,但是在这种情况下没有什么效果
if (!leak) {
this.clear(frame);
}
frame.src = this.dynamicDOMUrl;
}
,
clear: function (frame) {
if (frame) {
frame.contentWindow.document.write("");
frame.contentWindow.document.clear();
top.CollectGarbage();
}
}
};
</script>
</head>
<body>
<div>
<input type="button" value="dynamicDOMLeak" onclick="IFrameLeakTester.leak();"/>
<input type="button" value = "dynamicDOMUnLeak" onclick="IFrameLeakTester.unLeak();" />
</div>
<div>
<iframe id="frame" src="UnLeakIFrameContent.htm" height = "500px" width = "100%">
</iframe>
</div>
</body>
</html>
![](http://my.csdn.net/uploads/201205/15/1337097591_8719.png)
图 4. 刷新嵌套extjs例子的这个页面内存泄露情况
![](http://my.csdn.net/uploads/201205/16/1337097610_3620.png)
图 5. 不断刷新嵌套extjs例子的iframe内存泄露情况
从图4和图5中,我们可以看到刷新整个页面也是没有泄露的,但是刷新iframe却存在泄露,并且刷新的次数越多泄露越严重。综合前面iframe嵌套静态页面的例子,我们可以知道,IE可以缓存页面本身的DOM,以备再次刷新iframe的同一页面的时候用;但是如果iframe嵌套的页面中新建了DOM元素,那么每次打开这个页面的时候都会新建对应的DOM元素,从而导致严重的内存泄露。
对于怎样应对这种内存泄露的情况,我没有发现行之有效的方法;在网上搜到一些解决的方法,但是我测试了一下(单击dynamicDOMUnLeak按钮),没有什么效果,具体情况如下图
![](http://my.csdn.net/uploads/201205/16/1337097629_2798.png)
图 6. 解决泄露的代码没有效果
相关文章推荐
- 魔鬼的梦魇—验证IE中的JS内存泄露模式(一)
- 魔鬼的梦魇—验证IE中的JS内存泄露(二)
- 魔鬼的梦魇—验证IE中的js内存泄露模式(三)
- js在客户端验证密码强度,兼容FireFox和IE [转]
- IE8"开发人员工具"使用详解下(模式,JS调试,探查器)
- IE兼容模式下面,js中的json字符串不能有多余的逗号
- JQuery validate 在IE兼容模式下出现 js错误(成员找不到)的修正:
- JS密码强度验证(兼容IE,火狐,谷歌) -- 仿JQuery中文社区注册
- 关于ie和360兼容模式不支持js的instanceof
- JS 密码强度验证(兼容IE,火狐,谷歌)
- js非空验证兼容IE、FF浏览器
- js在客户端验证密码强度,兼容FireFox和IE
- 鄙人最新作JS验证组件采用策略模式易扩展
- JS获取IE版本号与HTML设置IE文档模式的方法
- jquery.validate.js 验证表单时,在IE当中未验证就直接提交的原因
- js ie 内存泄露与解决办法
- JS魔法堂:精确判断IE的文档模式by特征嗅探
- js在客户端验证密码强度,兼容FireFox和IE
- jquery.validate.js 在ie中丢失焦点的时候不触发验证
- JS密码强度验证(兼容IE,火狐,谷歌) -- 仿JQuery中文社区注册