论坛首页 Web前端技术论坛

有图片资源时的IE内存泄漏

浏览 4952 次
精华帖 (1) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-06-15   最后修改:2009-07-22
关于ie内存泄漏详细信息就不说了,因为网上资料太多了,本地对象和js对象循环引用就会导致内存泄漏(貌似是因为本地对象和js对象的垃圾回收是由各自独立的引擎进行的,js引擎和DOM(COM)引擎),查看泄漏的工具也很多(这里有一些介绍:http://zivn.org/zivn/archives/tag/memory-leaks).

ie7做了改进,会释放绑定在dom上的js对象(在页面重新加载时),使得js的gc可以回收资源(已经形成的循环引用占用的资源在当前页面无法得到回收),引用一篇文章的话说是这样的(http://www.iteye.com/topic/301496):
"ie7的改进只是对于页面dom树上dom进行清除js引用,对于已经不在页面上但是还有js引用的ie7也是无能为力的
所以不能
LeakedDiv.parentElement.removeChild(LeakedDiv);
而要
LeakedDiv.expandoProperty=null;
LeakedDiv.parentElement.removeChild(LeakedDiv);
才可以,其实即使这样使用Drip看还是有5个引用在LeakedDiv上,是不是泄漏不好说了,目前看来,ie上面较好的办法就是先别用removeChild了"

上面的说法可以从以下代码得到验证(重复刷新页面,内存不会回收,注释掉div01.parentNode.removeChild(div01)重刷页面,内存回收了...IE6依然是死都不回收)

		<div id="d01"><div id="d02">memoryTest</div></div>
		<script type="text/javascript">
			function memoryTest(){
				var a=[];
				for(var i=0;i<100000;i++){
				 a.push('a');
				}
				var div01=document.getElementById('d02');
				div01.kk=function(){};	//此处产生一个闭包,此作用域资源得不到释放,divA不会销毁,循环引用产生
				div01.parentNode.removeChild(div01);
			}
			memoryTest();
		</script>




内存泄漏,还有一种情况,内存一直在涨,不回收,但是在最小化浏览器和刷新浏览器的时候,内存会回收一部分,我一直很诧异这个问题,内存泄漏怎么还能回收呢?
原来是这样的,分析:
这里div1.oo=obj2;obj2.oo=div1形成一个dom/js循环引用(dom引用图片资源,用滤镜方式),div1内存不会释放,滤镜如果没加载完,remove掉div1,滤镜不会消耗内存,如果滤镜已经加载完毕,则会消耗内存,关键在于此处,滤镜消耗的内存不会得到释放,但是在刷新浏览器和最小化浏览器时内存会得到释放.
猜测ie7 dom引擎渲染页面是这么做的,在最小化浏览器的时候ie7会遍历一下dom树,将不在dom树的图片资源清除出去,不管拥有图片资源的dom是否被引用,限于以滤镜方式加载的图片,以img src加载方式的图片复杂一些,刷新不会回收内存,但在最小化时会释放一部分内存


代码如下:

		<body>
		<input type="button" value="dom增大内存" onclick="domMemory()"/>
		<input type="button" value="dom清除内存" onclick="clearMemory()"/>
		
	</body>
	<script>
	//重复的创建销毁dom元素不会导致内存泄漏	或者 内存不回收		
		var dinAry=[];
		var obj1={};
		obj1.ary=[];
		for(var i=0;i<10000;i++){
			obj1.ary.push(i.toString());
		}
		function domMemory(){
			for(var i=0;i<200;i++){
				var div1=document.createElement("div");
				var css1='width:200px;height:200px;filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src="img/a.png");"';
				div1.style.cssText = css1;
				div1.setAttribute("style",css1);
				var obj2={};
				div1.oo=obj2;		//引用一个全局变量
				obj2.oo=div1
				document.body.appendChild(div1);
				dinAry.push(div1);
		//					var fun1=function(){}
			}
			
			
			setTimeout(clearMemory,1000);	//确保图片加载完成,否则不会占用内存
		}
		function clearMemory(){
			var temp;
			while(temp = dinAry.pop()){
				document.body.removeChild(temp);
			}
		}
		
	</script>






网名: 天堂左我往右
   发表时间:2009-06-16  
re啊。。。BS IE的引用计数。。。
0 请登录后投票
   发表时间:2009-06-18  
恩  开发web application 的  要十分注意这个问题
0 请登录后投票
   发表时间:2009-06-19  
IE下发现的bug真不少,尤其是IE6。文章分析的很翔实,受益匪浅。谢谢
0 请登录后投票
   发表时间:2009-06-20  
谢谢捧场哈
0 请登录后投票
   发表时间:2009-06-22  
手动试了一下,在ie6下,点击dom增大内存,内存增加,点击dom清除内存,内存尚无减少....是不是我有那个地方错了?
0 请登录后投票
   发表时间:2009-06-26  
清除内存 那个按钮其实没用,只是为了测试在IE7下,不在dom树中的节点会造成内存泄漏...

感谢捧场哈
0 请登录后投票
   发表时间:2009-07-09  
上面两种 ie8 刷新后就回去了.
0 请登录后投票
   发表时间:2009-07-10  
ie8还是不错的...
期待后ie时代浏览器,哈哈
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics