Java理论与实践: 垃圾收集简史 - 编程入门网
费大量精力去检查并处理垃圾。标记-清除收集器还容易使堆产生碎片 ,这会产生区域性问题并可以造成分配失败,即使看来有足够的自由内存可用。
复制收集器 在另一种形式的跟踪收集器 ―― 复制收集器中,堆被分成两个大小相等的 半空间,其中一个包含活跃的数据,另一个未使用。当活跃的空间占满以后,程 序就会停止,活跃的对象被从活跃的空间复制到不活跃的空间中。空间的角色就 会转换,原来不活跃的空间成为了新的活跃空间。 复制收集的优点是只访问活跃的对象,这意味着不会检查垃圾对象,也不需 要将它们页交换到内存中或者送到缓存中。复制收集器的收集周期时间是由活跃 对象的数量决定的。不过,复制收集器因为要将数据从一个空间复制到另一个空 间、调整所有引用以指向新备份而增加了成本。特别是,长寿的对象在每次收集 时都要来回复制。 Java理论与实践: 垃圾收集简史(3)时间:2010-12-22 IBM Brian Goetz堆整理 复制收集器有另一个好处,活跃对象集会被整理到堆的底部。这不仅改进了 用户程序的引用区域性并消除了堆碎片,而且极大地减少了对象分配的成本 ― ― 对象分配变成了在堆顶部的指针上增加指针。不需要维护自由列表或者后备 列表,或者使用性能最佳或者第一合适的算法 ―― 分配 N 字节就是在堆顶部 指针上加 N 并返回前一个值这么简单,如清单 1 所示: 清单 1. 复制收集器中廉价的内存分配
为非垃圾收集语言实现了复杂内存管理方案的开发人员可能会对复制收集器 中廉价的内存分配感到吃惊 ―― 就是指针加法这么简单。以前的 JVM 实现没 有使用复制收集器 ―― 这可能是对象分配是昂贵的这一想法是如此普遍的原因 之一,开发人员仍然下意识地假设分配成本与其他语言(如 C)类似,而事实上 在 Java 运行时中可能要廉价得多。不但是分配成本减少了,而且对于在下次收 集之前成为垃圾的对象,解除分配的成本为零,因为既不会访问也不会复制垃圾 对象。 标记-整理收集器 复制算法的性能很优异,但是它有一个缺点是需要两倍于标记-清除收集器所 需要的内存。标记-整理 算法结合了标记-清除和复制,避免了这个问题,代价 是增加了一些收集复杂性。与标记-清除类似,标记-整理是两阶段过程,在标记 阶段访问并标记每个活跃对象。然后,复制标记的对象,使所有活跃对象被整理 到堆的底部。如果每一次收集时进行彻底的整理,那么得到的堆就类似于复制收 集器的结果 ―― 在堆的活跃部分与自由部分有明确的界线,这样分配成本与复 制收集器相当。长寿的对象趋向于沉在堆的底部,这样就不会像在复制收集器中 那样反复复制它们。 选择哪一种呢? 那么 JDK 使用了哪种方式进行垃圾收集呢?在某种意义上,使用了所有的方 式。早期的 JDK 使用了单线程的标记-清除或者标记-清除-整理收集器。1.2 及 以后的 JDK 使用了混合的方式,称为 分代收集,其中根据对象的年龄将堆分为 几个部分,不同的代是用不同的收集算法收集的。 分代收集证明是非常高效的,尽管在运行时它需要更多的簿记。在下一个月 的 Java 理论与实践 中,除了介绍 1.4.1 JVM 提供的所有其他垃圾收集选项之 外,我们还将探讨分代收集是如何工作的以及 1.4.1 JVM 是如何使用它的。在 下下篇文章中,我们将分析垃圾收集对性能的影响,包括揭示与内存管理有关的 性能神话。 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |