GC与JS内存泄露

作者:alucard 来源:Alibaba.com UED 时间:2010-09-25 19:01:00 

Javascript有没有内存泄露?如果有,如何避免?鉴于最近有好几个人问到我类似的问题,看来大家对这部分内容还没有系统的研究过,因此,打算在这里把个人几年前整理的一些资料和大家分享一下。

首先,可以肯定的说,javascript的一些写法会造成内存泄露的,至少在IE6下如此。因此,在IE6迟迟不肯退休的今天,我们还是有必要了解相关的知识(虽然大部分情况下,js造成的这点内存泄露不是致使电脑运行变慢的主要原因)。相关的研究主要集中在05-07这几年,本文并没有什么新的观点,如果当年有研究过的朋友,可以直接忽略。

作为前端开发人员,了解这些问题的时候,需要知其然也知其所以然,因此,在介绍js内存泄露前,我们先从为什么会有内存泄露谈起。

说道内存泄露,就不得不谈到内存分配的方式。内存分配有三种方式,分别是:

一、静态分配( Static Allocation ):静态变量和全局变量的分配形式。如果把房间看做一个程序,我们可以把静态分配的内存当成是房间里的耐用家具。通常,它们无需释放和回收,因为没人会天天把大衣柜当作垃圾扔到窗外。

二、自动分配( Automatic Allocation ):在栈中为局部变量分配内存的方法。栈中的内存可以随着代码块退出时的出栈操作被自动释放。

这类似于到房间中办事的人,事情一旦完成,就会自己离开,而他们所占用的空间,也随着这些人的离开而自动释放了。

三、动态分配( Dynamic Allocation ):在堆中动态分配内存空间以存储数据的方式。也就是程序运行时用malloc或new申请的内存,我们需要自己用free或delete释放。动态内存的生存期由程序员自己决定。一旦忘记释放,势必造成内存泄露。这种情况下,堆中的内存块好像我们日常使用的餐巾纸,用过了就得扔到垃圾箱里,否则屋内就会满地狼藉。因此,懒人们做梦都想有一台家用机器人跟在身边打扫卫生。在软件开发中,如果你懒得释放内存,那么你也需要一台类似的机器人——这其实就是一个由特定算法实现的垃圾收集器。而正是垃圾收集机制本身的一些缺陷,导致了javascript内存泄露。

几年前看过一篇叫《垃圾回收趣史》的文章,里面对垃圾回收机制进行了深入浅出的说明。

就像机械增压这种很多豪车作为卖点的技术,其实上个世纪10年代奔驰就在使用了一样,垃圾回收技术诞生也有很长的时间了。1960 年前后诞生于 MIT 的 Lisp 语言是第一种高度依赖于动态内存分配技术的语言,Lisp 中几乎所有数据都以“表”的形式出现,而“表”所占用的空间则是在堆中动态分配得到的。 Lisp 语言先天就具有的动态内存管理特性要求 Lisp 语言的设计者必须解决堆中每一个内存块的自动释放问题(否则, Lisp 程序员就必然被程序中不计其数的 free 或 delete 语句淹没),这直接导致了垃圾收集技术的诞生和发展。

而三种最基本的垃圾回收算法,也在那个时候一起出现了。下面我们一个一个了解一下:

引用计数(Reference Counting)算法:这个可能是最早想到的方法。形象点说,引用计数可以这么理解,房子里放了很多白纸,这些纸就好比是内存。使用内存,就好比在这些纸上写字。内存可以随便使用,但是,有个条件,任何使用一张纸的人,必须在纸的一角写上计数1,如果2个人同时使用一张纸,那么计数就变成2,以此类推。当一个人使用完某张纸的时候,必须把角上的计数减1,这样,一旦当计数变为0,就满足了垃圾回收条件,等在一旁的机器人会立即把这张纸扔进垃圾箱。基于引用计数器的垃圾收集器运行较快,不会长时间中断程序执行,适宜地必须 实时运行的程序。但引用计数器增加了程序执行的开销;同时,还有个最大的问题,这个算法存在一个缺陷,就是一旦产生循环引用,内存就会被泄露。举个例子,我们new了2个对象a和b,这时,a和b的计数都是1,然后,我们把a的一个属性指向b,b的一个属性指向a,此时,由于引用的关系,a和b的计数都变成了2,当程序运行结束时,退出作用域,程序自动把a的计数减1,由于最后a的计数仍然为1,因此,a不会被释放,同样,b最后的计数也为1,b也不会被释放,内存就这么泄露了!

标签:内存,js,javascript,IE
0
投稿

猜你喜欢

  • sql server如何得到插入一条记录后最新的ID?

    2009-11-15 20:06:00
  • 学习ASP.NET八天入门:第二天

    2007-08-07 13:24:00
  • ACCESS模糊查询出现"内存溢出"

    2009-08-13 14:25:00
  • 奇淫技巧和西天取经

    2009-08-24 12:34:00
  • 管理员必读10个重要MySQL客户启动选项

    2008-06-07 16:57:00
  • AJAX快速入门之HTTP协议基础

    2008-01-16 19:04:00
  • SQLServer 2005中如何列所有存储过程

    2008-11-24 17:39:00
  • 支付宝lab logo设计创意发想

    2009-11-12 12:44:00
  • asp如何利用当前时间生成随机函数?

    2010-01-01 15:44:00
  • 迎来2009年CSS裸奔节(CSS Naked Day )

    2009-04-24 12:41:00
  • Ajax的错误处理机制探讨

    2007-09-07 09:53:00
  • 对SQL Server数据库进行优化的经验总结

    2010-07-26 14:52:00
  • 从XML中读取数据到内存的实例

    2008-09-04 14:43:00
  • asp如何计算下载一个文件需要多长时间?

    2009-11-25 20:17:00
  • XMLHTTP错误The server name or address could not be resolved 的解决过程

    2009-12-26 18:33:00
  • Active Server Pages 错误 ASP 0201 修复方法

    2011-03-06 10:41:00
  • 用画为5.12地震受灾同胞们祈福

    2008-05-20 12:08:00
  • 保护MySQL数据库中重要数据的注意事项

    2009-01-19 11:55:00
  • js截取字符串的方法

    2008-04-20 17:06:00
  • 移动网站开发:标记语言

    2010-06-08 13:42:00
  • asp之家 网络编程 m.aspxhome.com