程序开发中遇到的Javascript 内存泄漏问题

内存泄漏,就是内存不能够被正确地配置,内存不能及时有效回收,他会导致程序执行效率降低甚至执行失败。

在浏览器领域,大部分都可能会出现内存泄漏问题,但是以IE最为多见,也最为严重,尤其是页面中有许多Javascript的交互效果的时候。其中涉及到循环结构(cyclic structure)、DOM对象属性、JavaScript对象属性以及垃圾回收器(garbage collector)。

循环结构(cyclic structure),是指一个DOM对象包含JavaScript对象参数(事件处理函数),JavaScript对象又包含了DOM对象的属性参数。(比如给某个超链接A添加一个onclick事件函数,这时候A就有了相应的事件处理函数,而JavaScript函数对象中也有了A的onclick属性)。

当循环结构(cyclic structure)形成时如果没有别的参数传递给DOM对象或者Javascript函数对象,JavaScript的垃圾回收器(一个自动内存管理器)就会把这两个对象的内存释放并重新进行配置,但是IE的DOM对象属性参数并不能由JavaScript管理清除(不能清除DOM对象的属性参数),而他自己的内存管理机制并不能理解循环结构(cyclic structure)的垃圾回收机制。因此,当循环结构(cyclic structure)的垃圾回收条件形成时,IE也不能进行正确的内存回收管理,导致内存泄漏。当然,这只有在循环结构的未回收内存的数量达到很大的数量级的时候,才会出现明显的内存泄漏症状。



最近做一个公司的业务系统,公司要求能尽可能的与c/s近似,也就是如c/s一样,点击文本框可以弹出此项目的相关内容,进行选择输入。

     我使用了弹出窗口,然后在子窗口双击选中项目,把选中的值返回给父窗体。

     在系统做完了之后,在客户使用的过程,由于客户使用的是512m的内存配置,所以在打开了30--40个窗体之后,ie的虚拟内存占用量达到近200m,从而使系统变慢,javascript的运行也变慢了。



      在google搜了一下之后,才知道可能是由于ie的内存泄漏引起的。具体可以参看www.cnblogs.com中的相关文章。



      我使用任务管理器,打开一个弹出窗口,ie内存就增加1-3m,然后关闭窗口,有时内存并不释放,有时才释放几十k。看来问题出在了内存释放上面。



      接着按内存释放这个思路,进行搜索查找方法,来进行解决这个问题。我找到一个javascript未公开的函数CollectGarbage,这个函数是用来进行内存释放的。我在所有的弹出窗口结束之前把所有的自己定义的javasctip的变量设置为null,并调用CollectGarbage函数。



      javascript中把变量设为null,javascript并不会把内存释放,当下次再次定义变量时,就会覆盖此变量所在的内存。如果不设为null,javascript再次定义变量时,会开辟一个新的内存空间。



      在使用以上处理之后,再次打开窗口,ie的内存每次还是增加1-3m,但是在关闭窗口之后,则ie会释放一定数量的内存在500k至2m。起到了一定的作用。

       由于我在页面中使用了第三方的控件,第三方的控件中的javascript中的内存是如何管理,就不是由我来控制的了。

    

1.javascript内存释放的方法示例



  把所有上级函数的参数即使设为null,并使用CollectGarbage来释放内存。 



示例

  <script> 

  

  //32M 

  function   AllocMem() 

  { 

  var   str="12345678"; 

  for(var   i=3;i<24;i++) 

  str+=str; 

  return   str; 

  } 

  

  function   A(a) 

  { 

  a=null; 

  return   r; 

  function   r() 

  { 

  } 

  } 

  var   f=A(AllocMem()); 

  alert(1); 

  CollectGarbage(); 

  //明显,已经释放了。 

  r=null; 

  alert(2); 

  CollectGarbage(); 

  

  </script> 

  

  里面对于内存释放的规则(脚本层)已经理解得很透了。 

  (每一层菜单分配?M的内存.对着任务管理器才看到情况) 



注:

CollectGarbage()通常会在核心推出内存,因就是IE或NS程序结束的时候才会调用.这样才是安全的 



说明:

1)   如果你在另一个window中keep了该window中的object的reference,即使关闭该window,内存也没有释放 

  

  As   you   might   know,   windows   opened   with   window.open()   may   share   a   process   with   its   opener   (_blank   or   _new     window   may   not).   That   is,   even   if   you   see   those   two   windows   on   the   desktop,   if   you   look   at   the   process   table   in   the   Task   Manager,   you   may   only   see   one   IEXPLORE.EXE   running.   Memory   may   only   be   released   when   the   process   is   terminated 

   

2)更糟糕的是,如果你keep的是一个DOM   object的reference,   关闭该object   所在window,   IE会crash,   报内存错误(或者要求,重新启动) 

  

  I   would   say   this   looks   like   a   bug,   you   might   want   to   report   to   Microsoft

http://www.cnblogs.com/chillsrc/archive/2006/12/28/606544.html

IE下产生内存泄漏的几种情况以及解决办法 - [javascript开发]

1、给DOM对象添加的属性是一个对象的引用。
范例:   
var MyObject = {};   
document.getElementById('myDiv').myProp = MyObject;   
解决方法:   
在window.onunload事件中写上: document.getElementById('myDiv').myProp = null;     
2、DOM对象与JS对象相互引用。
范例:   
function Encapsulator(element) {   
  this.elementReference = element;   
  element.myProp = this;   
}   
new  Encapsulator(document.getElementById('myDiv'));   
解决方法:   
在onunload事件中写上: document.getElementById('myDiv').myProp = null;   
   
3、给DOM对象用attachEvent绑定事件。
范例:   
function doClick() {}   
element.attachEvent("onclick", doClick);   
解决方法:   
在onunload事件中写上: element.detachEvent('onclick', doClick);   
   
4、从外到内执行appendChild。这时即使调用removeChild也无法释放。
范例:   
var parentDiv =  document.createElement("div");   
var childDiv = document.createElement("div");   
document.body.appendChild(parentDiv);   
parentDiv.appendChild(childDiv);   
解决方法:   
从内到外执行appendChild:   
var parentDiv =  document.createElement("div");   
var childDiv = document.createElement("div");   
parentDiv.appendChild(childDiv);   
document.body.appendChild(parentDiv);   
 
 
5、反复重写同一个属性会造成内存大量占用(但关闭IE后内存会被释放)。
范例:   
for(i = 0; i < 5000; i++) {   
  hostElement.text = "asdfasdfasdf";   
}   
这种方式相当于定义了5000个属性!   
解决方法:   
其实没什么解决方法:P~~~就是编程的时候尽量避免出现这种情况咯~~   
   
说明:   
1、以上资料均来源于微软官方的MSDN站点,链接地址:   
http://msdn.microsoft.com/librar ... e_leak_patterns.asp   
大家可以到上面这个地址中看到详细的说明,包括范例和图例都有。只是我英文不太好,看不太懂,如果我上述有失误或有需要补充的地方请大家指出。   
  2、对于第一条,事实上包括 element.onclick = funcRef 这种写法也算在其中,因为这也是一个对对象的引用。在页面onunload时应该释放掉。   
3、对于第三条,在MSDN的英文说明中好像是说即使调用detachEvent也无法释放内存,因为在attachEvent的时候就已经造成内存“LEAK”了,不过detachEvent后情况还是会好一点。不知道是不是这样,请英文好的亲能够指出。   
  4、在实际编程中,这些内存问题的实际影响并不大,尤其是给客户使用时,客户对此绝不会有察觉,然而这些问题对于程序员来说却始终是个心病 --- 有这样的BUG心里总会觉得不舒服吧?能解决则给与解决,这样是最好的。

你可能感兴趣的:(JavaScript,编程,IE,配置管理,项目管理)