垃圾收集趣史java垃圾收集算法- - - - - -王咏刚

):静态变量和全局变量的分配形式。我们可以把静态分配的内存看成是家里的耐用家具。通常,它们无需释放和回收,因为没人会天天把大衣柜当作垃圾扔到窗外。):在栈中为局部变量分配内存的方法。栈中的内存可以随着代码块退出时的出栈操作被自动释放。这类似于到家中串门的访客,天色一晚就要各回各家,除了个别不识时务者以外,我们一般没必要把客人捆在垃圾袋里扫地出门。):在堆中动态分配内存空间以存储数据的方式。堆中的内存块好像我们日常使用的餐巾纸,用过了就得扔到垃圾箱里,否则屋内就会满地狼藉。像我这样的懒人做梦都想有一台家用机器人跟在身边打扫卫生。在软件开发中,如果你懒得释放内存,那么你也需要一台类似的机器人这其实就是一个由特定算法实现的垃圾收集器。 餐巾纸的算法,它们的操作对象既不是静态变量,也不是局部变量,而是堆中所有已分配内存块。[@more@]) 技术简单而有趣的发展史。动笔之前,我站在窗边,望了望正在小区里装运垃圾的清洁车。和生活中环卫工人们清运垃圾的工作相似,软件开发里的垃圾收集其实就 是一种自动打扫和清除内存垃圾的技术,它可以有效防范动态内存分配中可能发生的两个危险:因内存垃圾过多而引发的内存耗尽(这和生活垃圾堵塞排污管道的 危险并没有什么本质的不同),以及不恰当的内存释放所造成的内存非法引用(这类似于我们在生活中买到了一瓶已经过期三年的牛奶)。 长安。今天,当我们在软件开发中体验自动垃圾收集的便捷与舒适时,我们至少应当知道,这种拒绝杂乱、追求整洁的垃圾收集精神其实是人类自古以来就 已经具备了的。语言中第一次感受到垃圾收集技术的巨大魅力的,许多人也因此把和垃圾收集看成了密不可分的整体。但事实上,垃圾收集技术早在语言问世前多年就已经发展和成熟起来了,语言所做的不过是把这项神奇的技术带到了广大程序员身边而已。语言才是当之无愧的人选。年前后诞生于的语言是第一种高度依赖于动态内存分配技术的语言:中几乎所有数据都以表的形式出现,而表所占用的空间则是在堆中动态分配得到的。语言先天就具有的动态内存管理特性要求语言的设计者必须解决堆中每一个内存块的自动释放问题(否则,程序员就必然被程序中不计其数的或语句淹没),这直接导致了垃圾收集技术的诞生和发展说句题外话,上大学时,一位老师曾告诉我们,是对现代软件开发技术贡献最大的语言。我当时对这一说法不以为然:布满了圆括号,看上去像迷宫一样的语言怎么能比语言或语言更伟大呢?不过现在,当我知道垃圾收集技术、数据结构技术、人工智能技术、并行处理技术、虚拟机技术、元数据技术以及程序员们耳熟能详的许多技术都起源于语言时,我特别想向那位老师当面道歉,并收回我当时的幼稚想法。 语言与垃圾收集的密切关系,我们就不难理解,为什么垃圾收集技术的两位先驱者和同时也是语言发展史上的重要人物了。是之父,他在发明语言的同时也第一次完整地描述了垃圾收集的算法和实现方式;则在发展语言的过程中成为了今天好几种主流垃圾收集算法的奠基人和当时不少技术大师的经历相似,和在许多不同的技术领域里都取得了令人艳羡的成就。也许,在年代那个软件开发史上的拓荒时代里,思维敏捷、意志坚定的研究者更容易成为无所不能的西部硬汉吧。 ):静态变量和全局变量的分配形式。我们可以把静态分配的内存看成是家里的耐用家具。通常,它们无需释放和回收,因为没人会天天把大衣柜当作垃圾扔到窗外。):在栈中为局部变量分配内存的方法。栈中的内存可以随着代码块退出时的出栈操作被自动释放。这类似于到家中串门的访客,天色一晚就要各回各家,除了个别不识时务者以外,我们一般没必要把客人捆在垃圾袋里扫地出门。):在堆中动态分配内存空间以存储数据的方式。堆中的内存块好像我们日常使用的餐巾纸,用过了就得扔到垃圾箱里,否则屋内就会满地狼藉。像我这样的懒人做梦都想有一台家用机器人跟在身边打扫卫生。在软件开发中,如果你懒得释放内存,那么你也需要一台类似的机器人这其实就是一个由特定算法实现的垃圾收集器。 餐巾纸的算法,它们的操作对象既不是静态变量,也不是局部变量,而是堆中所有已分配内存块。)算法语言设计垃圾收集机制时,第一个想到的算法是引用计数算法。拿餐巾纸的例子来说,这种算法的原理大致可以描述为: 餐巾纸使用规约之引用计数 版的要求,画图之前,我必须先在餐巾纸的一角写上计数值,以表示我在使用这张餐巾纸。这时,如果你也想看看我画的蓝图,那你就要把餐巾纸上的计数值加,将它改为,这表明目前有个人在同时使用这张餐巾纸(当然,我是不会允许你用这张餐巾纸来擦鼻涕的)。你看完后,必须把计数值减,表明你对该餐巾纸的使用已经结束。同样,当我将餐巾纸上的内容全部誊写到笔记本上之后,我也会自觉地把餐巾纸上的计数值减。此时,不出意外的话,这张餐巾纸上的计数值应当是,它会被垃圾收集器假设那是一个专门负责打扫卫生的机器人捡起来扔到垃圾箱里,因为垃圾收集器的惟一使命就是找到所有计数值为的餐巾纸并清理它们。 有一段风趣而精辟的论述: 面前说:我知道如何设计一个更好的垃圾收集器了。我们必须记录指向每个结点的指针数目。耐心地给这位学生讲了下面这个故事:一天,一个学生走到面前说:我知道如何设计一个更好的垃圾收集器了从前有座山,山上有个庙,庙里有个老和尚的故事有异曲同工之妙。这说明,单是使用引用计数算法还不足以解决垃圾收集中的所有问题。正因为如此,引用计数算法也常常被研究者们排除在狭义的垃圾收集算法之外。当然,作为一种最简单、最直观的解决方案,引用计数算法本身具有其不可替 代的优越性。年代前后,,,等人对引用计数算法进行了数次改进,这些改进使得引用计数算法及其变种(如延迟计数算法等)在简单的环境下,或是在一些综合了多种算法的现代垃圾收集系统中仍然可以一展身手。)算法等人在年提出并成功地应用于语言的标记-清除算法。仍以餐巾纸为例,标记-清除算法的执行过程是这样的:你正在用餐巾纸吗?你用的是哪一张餐巾纸?机器人根据每个人的回答将人们正在使用的餐巾纸画上记号。询问过程结束后,机器人在餐厅里寻找所有散落在餐桌上且没有记号的餐巾纸(这些显然都是用过的废旧餐巾纸),把它们统统扔到垃圾箱里。标记和清除两大阶段。这种分步执行的思路奠定了现代垃圾收集算法的思想基础。与引用计数算法不同的是,标记-清除算法不需要运行环境监测每一次内存分配和指针操作,而只要在标记阶段中跟踪每一个指针变量的指向用类似思路实现的垃 圾收集器也常被后人统称为跟踪收集器()语言的成功,标记-清除算法也在大多数早期的运行环境中大放异彩。尽管最初版本的标记-清除算法在今天看来还存在效率不高(标记和清除是两个相当耗时的过程)等诸多缺陷,但在后面的讨论中,我们可以看到,几乎所有现代垃圾收集算法都是标记-清除思想的延续,仅此一点,等人在垃圾收集技术方面的贡献就丝毫不亚于他们在语言上的成就了。)算法于年发表了著名的论文一种使用双存储区的语言垃圾收集器()。在该论文中描述的算法被人们称为复制算法,它也被本人成功地引入到了语言的一个实现版本中。的复制算法:当然,对于用餐者往返奔波于南北两区之间的辛劳,垃圾收集机器人是决不会流露出丝毫怜悯的。本人在语言中的工作以外,从年代末到年代初,和等人也相继在语言的不同实现中对复制算法进行了改进,更是成功地将复制算法应用到了语言中。引用计数算法、标记-清除算法和复制算法都已在年前后相继问世,三种算法各有所长,也都存在致命的缺陷。从年代后期开始,研究者的主要精力逐渐转向对这三种传统算法进行改进或整合,以扬长避短,适应程序设计语言和运行环境对垃圾收集的效率和实时性所提出的更高要求。年代开始,随着科学研究和应用实践的不断深入,人们逐渐意识到,一个理想的垃圾收集器不应在运行时导致应用程序的暂停,不应额外占用大量的内存空间和资源,而三种传统的垃圾收集算法都无法满足这些要求。人们必须提出更新的算法或思路,以解决实践中碰到的诸多难题。当时,研究者的努力目标包括:资源。早期的运行环境收集内存垃圾的时间竟占到了系统总运行时间的!垃圾收集效率的低下直接造就了语言在执行速度方面的坏名声;直到今天,许多人还条件反射似地误以为所有程序都奇慢无比。计算的日子里,浪费客户的一半内存空间简直就是在变相敲诈或拦路打劫。或至少看上去不影响当前 进程的实时垃圾收集器,这显然是一件更具挑战性的工作。年代到年代的短短十几年中,一大批在实用系统中表现优异的新算法和新思路脱颖而出。正是因为有了这些日趋成熟的垃圾收集算法,今天的我们才能在或提供的运行环境中随心所欲地分配内存块,而不必担心空间释放时的风险。)算法加等于那样简单,我们必须引入一些全新的思路。年前后,,和等研究者陆续找到了正确的方向,标记-整理算法的轮廓也逐渐清晰了起来:)算法对实时垃圾收集过程中的技术难点进行了早期的研究,于年发表了题为多进程整理的垃圾收集()的论文,描述了一种被后人称为算法的实时垃圾收集算法。,,和等人也相继在此领域做出了各自的贡献。年,发表了串行计算机上的实时表处理技术(一文,系统阐述了多进程环境下用于垃圾收集的增量收集算法。等人的努力已经将实时垃圾收集的梦想变成了现实,我们再也不用为垃圾收集打断程序的运行而烦恼了。)算法年前后,善于在研究中使用统计分析知识的技术人员发现,大多数内存块的生存周期都比较短,垃圾收集器应当把更多的精力放在检查和清理新分配的内存块上。这个发现对于垃圾收集技术的价值可以用餐巾纸的例子概括如下:比如有些人喜欢在用餐前后各用掉一张餐巾纸,有的人喜欢自始至终攥着一张餐巾纸不放,有的人则每打一个喷嚏就用去一张餐巾纸机器人就可以制定出更完善的餐巾纸回收计划,并总是在人们刚扔掉餐巾纸没多久就把垃圾捡走。这种基于统计学原理的做法当然可以让餐厅的整洁度成倍提高。,和等人对内存垃圾的分类处理做了最早的研究。年,和发表了题为基于对象寿命的一种实时垃圾收集器(的论文。这篇著名的论文标志着分代收集算法的正式诞生。此后,在,,等人的共同努力下,分代收集算法逐渐成为了垃圾收集领域里的主流技术。这种效率上的提高在今天的虚拟机中得到了最好的证明。语言之后,许许多多传统的、现代的、后现代的语言已经把垃圾收集技术拉入了自己的怀抱。随便举几个例子吧:诞生于年的语言,年的语言,年的语言,年的语言,年的语言,年的语言,年的语言,年的语言它们都先后使用了自动垃圾收集技术。当然,每一种语言使用的垃圾收集算法可能不尽相同,大多数语言和运行环境甚至同时使用了多种垃圾收集算法。但无论怎样,这些实例都说明,垃圾收集技术从诞生的那一天起就不是一种曲高和寡的学院派技术。和语言,垃圾收集技术一样可以发挥巨大的功效。正如我们在学校中就已经知道的那样,和语言本身并没有提供垃圾收集机制,但这并不妨碍我们在程序中使用具有垃圾收集功能的函数库或类库。例如,早在年,和就成功地实现了一种使用保守垃圾收集算法()的函数库(参见 )。我们可以在语言或语言中使用该函数库完成自动垃圾收集功能,必要时,甚至还可以让传统的代码与使用自动垃圾收集功能的代码在一个程序里协同工作。语言在一夜之间将垃圾收集技术变成了软件开发领域里最为流行的技术之一。从某种角度说,我们很难分清究竟是从垃圾收集中受益,还是垃圾收集技术本身借的普及而扬名。值得注意的是,不同版本的虚拟机使用的垃圾收集机制并不完全相同,虚拟机其实也经过了一个从简单到复杂的发展过程。在虚拟机的版中,人们可以体验到的垃圾收集算法就包括分代收集、复制收集、增量收集、标记-整理、并行复制()、并行清除()、并发()收集等许多种,程序运行速度的不断提升在很大程度上应该归功于垃圾收集技术的发展与完善。却是第一种真正实用化的、包含了垃圾收集机制的通用语言运行环境。事实上,平台上的所有语言,包括、、、等等,都可以通过几乎完全相同的方式使用平台提供的垃圾收集机制。我们似乎可以断言,是垃圾收集技术在应用领域里的一次重大变革,它使垃圾收集技术从一种单纯的技术变成了应用环境乃至操作系统中的一种内在文化。这种变革对未来软件开发技术的影响力也许要远远超过平台本身的商业价值。或命令,也不愿把垃圾收集的重任交给那些在他们看来既蠢又笨的垃圾收集器。资源而对其望而却步,但二十多年前的程序员还曾因为高级语言速度太慢而坚持用机器语言写程序呢!在硬件速度日新月异的今天,我们是要吝惜那一点儿时间损耗而踟躇不前,还是该坚定不移地站在代码和运行环境的净化剂垃圾收集的一边呢?

垃圾收集趣史java垃圾收集算法- - - - - -王咏刚