纠结的IE浏览器内存泄漏的测试

在编写代码高亮脚本的时候,问了瓶子一个问题,就是在循环里处理删除DOM元素的时候,会动态改变NodeList的length,所以测试许久, 最后发现是这个问题,狂晕。但是期间谈到了一个关于removeChild的时候在IE下无法回收内存的泄漏问题,他展示了一个EXT里针对IE使用的方 法:


var div=document.getElementById("div");

var first=div.firstChild,next=first;

while(next){

var d=document.createElement("div");

d.appendChild(next);

d.innerHTML="";

next=div.firstChild;

}

///////////////////////////////////////////////////

//简单的removeChild方式:

var div=document.getElementById("div");

var first=div.firstChild,next=first;

while(next){

next.parentNode.removeChild(next);

next=div.firstChild;

}

  但是经过使用Drip工具(测试IE是否内存泄漏的工具,download),测试还是存在内存泄漏的问题,但是使用IE JS Leaks Detector却啥也检测不出来(全部的测试都检测不出来,就连网上都吹捧的内存泄漏的方式也检测不出来),还有使用了话说是Drip的增强版的sIEve(download),也测试不出来。既然这样,那就暂且信任Drip吧。下面几种传说中的内存泄漏的方式都是在Drip下测试的。

  在开始讲述之前,先大概了解一下javascript的GC机制:

  垃圾回收进程尝试推断何时可以安全地回收不再使用的变量,通常是通过判定程序是否能够通过变量之间形成的引用网络到达该变量。当确信变量是不可达的,就在它上面标上可以回收的记号,并且在回收器的下一次清理中(可能在未来的任意时刻)释放相关的内存。

  也就是说,垃圾回收机制会定时的检查程序中的对象,查看它是否跟别的对象之间已经完全断开了引用链而“孤单一人”,这时,垃圾回收机制就会回收这个 对象的内存,否则,将不会回收。所以说,对象在使用完了之后,就应该被回收内存,而不是一直占用着内存不放,导致浏览器的内存使用量节节飙升。

  第一种:既然上面谈到了关于removeChild,那就从它开始吧,通过Drip测试,简单的使用 removeChild删除子节点的方式确实存在内存泄漏,但是使用了上面EXT使用的方式,也还是存在。经过一番搜索,有文章说需要清除节点的全部属性 来实现内存的正确回收,那就进行了下面的测试。结果通过将节点的属性都delete掉之后,Drip显示没有内存泄漏了。


var div=document.getElementById("div");

var first=div.firstChild,next=first;

while(next){

div.removeChild(next);

for(var k in next){

delete next[k];

}

next=div.firstChild;

}

 第二种:将一个DOM对象和一个JS对象相互成为对方的属性。对于这点,IE官方也都有说法:在IE6中,对于 javascript object内部,jscript使用的是mark-and-sweep算法,而对于javascript object与外部object(包括native object和vbscript object等等)的引用时,IE 6使用的才是计数器的算法。也就是说,IE 6对于纯粹的Script Objects间的Circular References是可以正确处理的,可惜它处理不了的是JScript与Native Object(例如Dom、ActiveX Object)之间的Circular References。所以,当我们出现Native对象(例如Dom、ActiveX Object)与Javascript对象间的循环引用时,内存泄露的问题就出现了。当然,这个bug在IE 7中已经被修复了。(Fuck,难怪我用Drip测试不出来(系统是IE8的内核))。下面是我的一个测试:


function Encapsulator(element){

this.elementReference = element;

element.expandoProperty = this;

}

function SetupLeak2(){

var obj=new Encapsulator(document.getElementById("test"));

document.body.removeChild(document.getElementById("test"));

//alert(document.getElementById("test").expandoProperty); 出现错误

//说明从element.expandoProperty ---> obj的引用已经断开了

//但是从obj.elementReference到element的引用依然存在,

//这样的话在IE6下element就无法回收内存,但是其他浏览器的GC机制都会很好的处理了这个问题。

document.body.appendChild(obj.elementReference);

}

  第三种:将事件处理函数放在定义它的函数的内部。这种情况之前就看到过,回想下自己以前编写js的方式:外包一个自执行函数,里面定义闭包内的变量和功能函数,也不乏对事件处理程序的处理。这样是否会造成IE下的内存泄漏呢?下面是两个测试程序:


var test=function(){

var div=document.getElementById("test");

var i=0;

while((i++) < 20){

(function(index){

var o=document.createElement("p");

o.innerHTML="AAA";

o.onclick=function(){

alert("haha,leap");

}

div.appendChild(o);

o.onclick=null;

div.removeChild(o);

})(i);

}

}

function addEvent(){

var div=document.getElementById("event");

div.onclick=function(){

this.parentNode.removeChild(this);

}

}

  上面的一段程序也是从网上摘录下来做测试的,在闭包中动态生成一个div元素,并给它添加事件,事件处理程序写在闭包里面,也就是内涵在test函数里 面,可是在removeChild的时候,Drip下显示还是内存泄漏了,即使是把它的onclick属性设置为null也不行。第二个测试程序中,在事 件处理程序中通过removeChild删除当前节点的时候,也显示内存泄漏。

  第四种:在创建DOM对象时插入script。这个还是第一次看到。即是通过createElement创建DOM元 素的时候,直接在字符串中插入了js代码:document.createElement(“<div onclick=’foo();’>”),但是这种方式只在IE下有效。通过测试下面的程序,在Drip中也确实显示内存泄漏了

  var leakMemory=function(){

  for(i = 0; i < 5000; i++){

  var parentDiv = document.createElement("<div onClick='foo()'>");

  }

  }

  第五种:总是先将新创建的DOM对象插入到文档后,在对其进行其他操作。对于这点,我想象不到它是如何造成内存泄漏 的。而且,它跟页面优化的一些方式可能存在冲突。在某些情况下,在创建了DOM元素之后,先处理DOM的操作,最后才插入到文档中,这样可以避免尽可能的 由于reflow影响性能的情况。这可能就需要一个权衡了吧,因地制宜~

  总结:

  上面是本人通过使用Drip工具测试的结果,但是由于在sIEVE和JS Leaps Detector下测试都没发现内存泄漏的情况,所以纠结的很。经过这一番折腾,也不枉自己一番倒腾倒腾吧,在以后的编写代码中,可以或多或少的去避免这 些不必要的可能造成内存泄漏的情况出现。

  同时,如果有说错的地方,欢迎指正,共同学习~~

最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2025-01-19 04:32:05

纠结的IE浏览器内存泄漏的测试的相关文章

Dojo最佳实践-如何防止浏览器内存泄漏

对于浏览器端,尤其是 Internet Explorer 的内存泄漏问题及解决方法,已经有很深入和广泛的讨论.而本文将更多的讲解作为一个 Dojo 开发人员,如何正确使用 Dojo 的相关技术,遵循 Dojo 的编程模式来避免浏览器的内存泄露问题. Ajax 应用新的挑战 Ajax 技术已经被广泛的应用,其给 Web 用户带来全新的使用体验同时,也给 Web 开发人员带来了各种各样新的挑战.Ajax 应用中浏览器端内存泄露问题便是其中之一.作为一名 Web 前端开发人员,如果某天系统测试人员给您

软件测试中IE内存泄漏测试实例

测试某业数据门户进行功能测试时查看了一下任务管理器,发现IE进程竟然达到了423,145K,怀疑发生了内存泄漏,因此打算直接用IE的插件js memory leaks dector来检测一下,但是进行了一些可能引起内存泄漏的操作后,检测结果一直都很正常,并没有发现关于内存泄漏的地方,开发人员只好自己判断哪些IFRAM没有被销毁来优化系统,降低内存的使用. 下午的时候,查看以前的测试文档,发现用SIEVE来测试此类系统的IE内存泄漏时,通常在报表刷新的过程中,通常是会发生内存泄漏的,因此,用SIE

Android中导致内存泄漏的竟然是它----Dialog

一. 内存泄漏的 Bug 猛增 最近在 App 进行 mokey 测试的时候检测到一些内存泄漏问题.在前天的测试中,楼主一瞬间收到了4个这样的 Bug 单,瞬间心理无比纠结,真有千万只羊驼向我奔来. 登录页面出现内存泄漏??!!楼主的代码是如此的完美而无懈可击,这么可能出现这么多泄漏的问题? 插播什么是 Activity 泄漏:Android 中 Activity 代表一个页面,拥有一段生命周期,生命周期结束后,Activity 对象应当在之后某个合适的时机被 VM 回收内存.出现了泄漏就意味着

找出并解决 JavaScript 和 Dojo 引起的浏览器内存泄露问题

简介: 如果大量使用 JavaScript 和 Ajax 技术开发 Web 2.0 应用程序,您很有可能会遇到浏览器的内存泄漏问题.如果您有一个单页应用程序或者一个页面要处理很多 UI 操作,问题可能比较严重.在本文中,学习如何使用 sIEve 工具检测并解决内存泄漏问题,本文也包含内存泄漏问题的应用示例以及解决方案. 发布日期: 2012 年 4 月 09 日 级别: 中级 原创语言: 英文 访问情况 : 10932 次浏览 评论: 0 (查看 | 添加评论 - 登录)  平均分 (7个评分)

Node.js中内存泄漏分析

内存泄漏(Memory Leak)指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况.如果内存泄漏的位置比较关键,那么随着处理的进行可能持有越来越多的无用内存,这些无用的内存变多会引起服务器响应速度变慢,严重的情况下导致内存达到某个极限(可能是进程的上限,如 v8 的上限:也可能是系统可提供的内存上限)会使得应用程序崩溃. 传统的 C/C++ 中存在野指针,对象用完之后未释放等情况导致的内存泄漏.而在使用虚拟机执行的语言中如 Java.JavaScript 由于使用了 GC (Garbag

深入理解JavaScript程序中内存泄漏_javascript技巧

垃圾回收解放了我们,它让我们可将精力集中在应用程序逻辑(而不是内存管理)上.但是,垃圾收集并不神奇.了解它的工作原理,以及如何使它保留本应在很久以前释放的内存,就可以实现更快更可靠的应用程序.在本文中,学习一种定位 JavaScript 应用程序中内存泄漏的系统方法.几种常见的泄漏模式,以及解决这些泄漏的适当方法. 一.简介 当处理 JavaScript 这样的脚本语言时,很容易忘记每个对象.类.字符串.数字和方法都需要分配和保留内存.语言和运行时的垃圾回收器隐藏了内存分配和释放的具体细节. 许

【转贴】了解 JavaScript 应用程序中的内存泄漏

转贴:http://www.ibm.com/developerworks/cn/web/wa-jsmemory/ 检测和解决内存问题 Ben Dolmar, 软件开发人员, The Nerdery   简介: 垃圾回收解放了我们,它让我们可将精力集中在应用程序逻辑(而不是内存管理)上.但是,垃圾收集并不神奇.了解它的工作原理,以及如何使它保留本应在很久以前释放的内存,就可以实现更快更可靠的应用程序.在本文中,学习一种定位 JavaScript 应用程序中内存泄漏的系统方法.几种常见的泄漏模式,以

CSS雪碧图会占用太多浏览器内存吗?

可能是某篇微博的关系,今天有人来评论说,使用雪碧图,内存会暴涨的...这个问题讨论的也蛮多了,那,到底,使用雪碧图后,会占用很多内存吗? 实验: 下午做了个简单的实验,用99个128px*128px的png 32图片,写了三个页面来做测试: 只用img标签调用: 用css分别调用每个png图片做背景: 使用雪碧图做背景 然后分别用Chrome.IE6/7/8/9.Firefox做测试,具体的数据我这里就不详细列了,感兴趣的话可以自测一下. 结论: 在各浏览器下,三个页面占用的内存相当,只有很小的

oracle 9i 的内存泄漏问题

oracle|问题  近期在linux平台上写了一个程序需要通过oracle 9i的客户端调用PL/SQL, 在调试时发现有内存泄漏问题, 以为程序有bug, 检查了n遍也没有发现问题(呜呜,郁闷死了), 后来才找到资料说时oracle 9i的客户端有内存泄漏. 总结一下:1. 当程序为多进程模式时会出现内存泄漏,而且泄漏速度很快, 在单进程模式下(DEFAULT)就没有这个问题2. 只在UNIX和linux系统上出现, window系统上没有发现.3. 不管是pro*c和OCI都会有这个问题