下载此文档

JVM中的垃圾收集.docx


文档分类:IT计算机 | 页数:约19页 举报非法文档有奖
1/19
下载提示
  • 1.该资料是网友上传的,本站提供全文预览,预览什么样,下载就什么样。
  • 2.下载该文档所得收入归上传者、原创者。
  • 3.下载的文档,不会出现我们的网址水印。
1/19 下载此文档
文档列表 文档介绍
Java垃圾收集算法简介
任何垃圾收集算法必须完成两件事情。首先,它必须检测出垃圾对象。其次,它必须回收垃圾对象所占用的堆空间并使之对程序重新可用。
垃圾检测通常通过定义一个根引用集并计算其可达对象集的方式来实现。一个对象,如果可以通过某条始于根引用的引用路径而被执行程序访问到的话,则称其为可达的(reachable)。对程序而言,根引用始终是可以访问的。一个对象如果是可达的,则称其为活动对象;否则就被称为垃圾,因为它对程序的未来执行不再有任何影响。
根引用集的构成取决于JVM的具体实现,但总是包含所有栈帧中局部变量区和操作数栈所持有的引用以及保存在静态变量中的引用。根引用的另外一个来源是常量池,已装载类的常量池可能保存有对堆中一些字符串的引用,这些字符串往往是类名、父类名、父接口名、域名、域签名、方法名和方法签名等。根引用还有一个可能来源就是那些传递给本地方法(native method)但尚未被其释放的引用。根引用的另一个潜在来源是JVM的运行时数据区,因为某些实现会把JVM运行时数据区的一部分放在堆上,例如方法区中的类数据本身。
可达对象集包含所有通过根引用可以直接或间接被程序访问到的对象,从技术角度讲,可达对象集是“指向”关系下根引用集的传递闭包。
区分活动对象和垃圾的两个基本方法是引用计数和追踪。JDK中的标准垃圾收集器全部采用了追踪的办法,虽然具体形式各不相同。
一、引用计数收集器
引用计数是垃圾收集的早期策略。在这种方法中,堆中的每个对象都有一个引用计数。当对象被创建并且指向其引用被赋值给一个变量后,该对象的引用计数被设置为1。以后每当其引用被赋值给一个不同的变量时,该对象的引用计数就加1。当持有该对象引用的变量离开其作用域或者被赋给一个新值时,该对象的引用计数就减1。任一对象一旦其引用计数变为0,就成为垃圾。一个对象一旦被当作垃圾收集后,它所引用的所有其他对象的引用计数必须相应递减。这样,对一个对象的垃圾收集可能引发连续的对其他对象的垃圾收集。
该方法的好处是,引用计数收集器算法简单,适于做增量收集,对于程序不能被长时间打断的实时环境特别适合,另外,收集过程也有助于改进引用局部性。坏处就是,引用计数无法检测出不可达的循环结构(两个或多个对象之间相互引用),因为它们的引用计数永远不会为0。另一个坏处就是每次增减引用计数都带来额外开销,而且该算法还需要编译器的高度配合。正是由于这些固有缺陷,引用计数算法在生产环境中很少使用。
二、追踪收集器
追踪收集器从根引用开始探寻并描画对象引用图。探寻过程中遇到的对象会以某种方式被打上标记。通常来说该标记既可保存在对象本身,也可保存在单独的位图中。探寻结束后未被标记的对象就是不可达的对象,可被当作垃圾收集。
基本的追踪算法被称作“标记并清理”(mark and sweep)。该名字指出了垃圾收集过程的两个阶段。在标记阶段,垃圾收集器遍历引用树,标记每一个遇到的对象。在清理阶段,未被标记的对象被释放,相应内存被返还待用。在JVM中,清理阶段必须包括对象的了结(finalization)。
标记并清理算法实现简单,可以轻易回收循环结构,而且不存在为维护引用计数而付出的额外开销和对编译器的依赖。但是它也有不足,其中最大的问题是,在清理阶段,堆中的所有对象,不论是否可达,都会被访问。一方面这对于可能有页面交换的堆所依赖的虚存系统有着非常负面的性能影响;另一方面,因为其中很大一部分对象可能是垃圾,这就意味着垃圾收集器把大量精力都花费在检查和处理垃圾上面了。无论从哪个角度来看,该算法都可能产生收集暂停时间过长、收集开销偏大的问题。标记并清理收集器的另一个不足是它容易导致堆的碎片化,从而引发引用局部性或者大对象分配失败等方面的问题。
三、压缩收集器
JVM的垃圾收集器很可能拥有一个对付堆碎片的策略。标记并清理收集器通常采用的两种策略是压缩或拷贝。这两种方法都是通过快速移动对象来减少堆碎片。压缩收集器把活动对象越过空闲内存区滑动到堆的一端,在这个过程中,堆的另一端就变成了一块大的连续空闲区。所有指向被移动对象的引用也被更新,指向新的位置。
为了更好的理解压缩过程,可以将堆比作书架的一格,其中一部分放满了不同厚度的图书。空闲空间就是图书之间的空隙。压缩就是将所有图书朝一个方向推移,以弥合所有空隙。它从最靠近隔板的图书开始,将它推向隔板,然后将离隔板第二近的图书推向第一本图书,接着将第三本图书推向第二本图书,依此类推。最后,所有图书在一端,所有空闲空间在另一端。
被移动对象的引用更新可以通过为对象引用添加一层间址而得到简化。对象引用不再直接指向堆中的对象,而是指向对象句柄表中的一个表项,该表项中的对象句柄才直接指向堆中的实际对象。这样,

JVM中的垃圾收集 来自淘豆网m.daumloan.com转载请标明出处.

相关文档 更多>>
非法内容举报中心
文档信息
  • 页数19
  • 收藏数0 收藏
  • 顶次数0
  • 上传人花开花落
  • 文件大小277 KB
  • 时间2018-11-20
最近更新