郑剑峰

导航

silverlight内存问题总结(二)—javascript内存泄露

周末或者是放假时候,睡眠质量都是出奇地好,昨天晚上十点多就开始发困,一觉到天亮,六点多就爬起来,精神抖擞,知道什么叫压力了吧!

      对于javasript这门语言,我的感触还是比较多的,从毕业到现在这门语言我一直在使用。在ASP年代末期,这门语言开始被很多开发人员所鄙视,很多人都觉得JavaScript只会弹出alert,只会实现一些简单的功能,最让人厌恶的是出现语法错误时候,会连续不断地弹出错误,直到开发人员绝望为止,直到前端用户窒息为止。随着Ajax 的出现,Google Map的成功,以及各种JS框架出现,JavaScript开始再一次被开发人员重视它,CSDN 曾经一度用“王者归来”这四个字来形容它。相比.net而言,我的javscript经验应该是比较多的,从毕业到现在,一直在用从未间断过,几个流行框架 Ext,jQuery,prototype 都有使用过,对JS的面向对象的理解还是比较到位,对JAVASCRIT 在IE系列浏览器和Firefox之间的差异也略知一二,当然随着IE9的出现,这种差异会越来越少。曾经有一个想法,把gof 的23个设计模式用JavaScript实现,不过后来发现在博客园上已经有人这么做了,我的兴致一下子荡然无存。

    两块silverlight之间的数据通信,需要拿javascript做桥梁,因为好几个线程都是在死循环的跑,有些数据交互是要用到javascript,导致很多javascript代码一直在死循环调用,由此而引出内存泄露。

    javascript的内存释放也是自动回收的,基本原理也是当一个对象没人任何指针指向它时垃圾回收器就可以启动回收了。造成javascript 泄露的主要原因:循环引用闭包。循环引用道理其实很好懂 如A=》B  B=》C  C=》A,导致 A,B,C三个对象都无法释放,不要小看该列子,当代码多起来庞大起来,这三者的关系是很难被发现。 至于闭包,作用域链原理,网上有很多介绍的文章,无奈由于专业的缘故,本人没学过编译原理,所以看这些文章有些吃力,有兴趣可以查阅(http://kevinpeng.javaeye.com/blog/682653)。闭包泄露很多时候都是由于javascript对象和Dom互相引用,以及一些事件订阅后又没有拆除这些订阅造成.

DOM引用造成的内存泄露:

      function  LeakMemory()  // This function can cause  Cross-Page Leaks
        {
            
var  hostElement  =  document.getElementById( " hostElement "
);
            
//  Do it a lot, look at Task Manager for memory response 

            
for (i  =   0 ; i  <   5000 ; i ++ )
            {
                
var  parentDiv  = document.createElement( " <div onClick='foo()'> "
);
                
var  childDiv  = document.createElement( " <div onClick='foo()'> "
);
                
//  This will leak a temporary object

                parentDiv.appendChild(childDiv);
                hostElement.appendChild(parentDiv);
                hostElement.removeChild(parentDiv);
                parentDiv.removeChild(childDiv);
                parentDiv 
=   null
;
                childDiv 
=   null
;
            }
            hostElement 
=   null
;
        }
        
function  CleanMemory()  //   This Function can not  cause Cross-Page Leaks

        {
            
var  hostElement  =  document.getElementById( " hostElement "
);
            
//  Do it a lot, look at Task Manager for memory response 

            
for (i  =   0 ; i  <   5000 ; i ++ )
            {
                
var  parentDiv  =   document.createElement( " <div onClick='foo()'> "
);
                
var  childDiv  =   document.createElement( " <div onClick='foo()'> "
);
                
//  Changing the order is important, this won't leak

                hostElement.appendChild(parentDiv);
                parentDiv.appendChild(childDiv);
                hostElement.removeChild(parentDiv);
                parentDiv.removeChild(childDiv);
                parentDiv 
=   null
;
                childDiv 
=   null
;
            }
            hostElement 
=   null
;
        }
        
</ script >

    
</ head > 
    
< body >
        
< button onclick = " LeakMemory() " > Memory Leaking Insert </ button >
        
< button onclick = " CleanMemory() " > Clean Insert </ button >
        
< div id = " hostElement " ></ div >
    
</ body >
</ html >

事件的订阅后没退订后造成的内存泄露:

function  leakmaybe() {
var  elm  =  document.createElement( " DIV "
);
  elm.onclick 
=   function
() {
return   2   +   2
;
  }
}
for  ( var  i  =   0 ; i   10000 ; i ++
) {
  leakmaybe();
} //上述循环中不断调用leakmaybe,每调用一次就会订阅一个onclick事件,如果是死循环的话,就会出现泄露。

javascript的在IE系列的内存泄露很多都是IE浏览器本身的BUG,但是微软死活不认帐,Eric Lippert是IE引擎开发组的成员,下面是他的原话:Don't use closures unless you really need closure semantics. In most cases, non-nested functions are the right way to go.他把这个BUG推给开发人员,认为是开发人员使用不当造成。Silverlight 内存释放不了,微软也不怎么认账,后面文章会提到。

    关于javascript 内存泄露,我也查阅了很多文章,但是我和我实际项目中都不怎么搭调,唯一个搭调的是setTimeout和setInterval,我在网上查了一下 很多人说这两个方法在计数器方面会造成内存泄露,但是我自己本机上做了测试不会泄露,好像IE6好像会,但是IE8绝对不会,我自己本机是IE8的。其实setTimeout和setInterval只是创造了一种死循环的环境,实际内存泄露应该不关他们的事情。最后发现内存泄露是由于这句话 :     

 eval("var list=" + a),这行代码主要是把一个字符串解析成javascript对象,据国外的老鸟解释,在解析的时候会生成一个临时对象,这个临时对象没办法释放,导致泄露,一个晚上泄露大概在14M左右。还有一个泄露地方是心跳验证(验证使用权限的),每跳一次都要发起AJAX请求,我估计是AJAX对象每次都重新生成,但是又没办法释放导致的,这个地方造成的泄露是一个晚上36M。最后给一个技巧,如果页面是javascript泄露造成的,只要最小化一下内存就会释放的掉,这是衡量JS泄露的个人的一个小技巧,当然还有待有大量事实的验证

posted on 2010-10-28 14:53  郑剑峰  阅读(981)  评论(0编辑  收藏  举报