您的位置:首页 > 编程语言 > Java开发

Java垃圾回收原理(2)

2017-09-20 14:16 260 查看
Java虚拟机采用一种自适应的垃圾回收技术。依据的思想:对任何“活”的对象,一定能最终追溯到其存活在堆栈或静态存储区之中的引用。这个引用链条可能会穿过数个对象层次。由此,如果从堆栈和静态存储区开始,遍历所有的引用,就能找到所有活的对象。对于发现的每个引用,必须追踪它所引用的对象,然后是此对象所包含的所有的引用,如此反复进行,直到“根源于堆栈和静态存储区的引用”所形成的网络全部被访问为止。至于如何处理找到存活的对象,取决于不同的Java虚拟机的实现。有一种名为停止-复制。显然这意味着,先暂停程序的运行,然后将所有存活的对象从当前堆复制到里一个堆,没有被复制的全部都是垃圾。当对象被复制到新堆时,它们是一个挨着一个,所以新堆保持紧凑排列,然后就可以按前述方法简单、直接地分配空间了。
当然这种所谓“复制式回收器”,效率会降低。为了避免这种情况,一些Java虚拟机会进行检查:要是没有新垃圾产生,就会转换到另一种工作模式。这种模式称为标记-清扫。这个方式速度会很慢,但是当只会产生少量的垃圾甚至不会产生垃圾时,她得速度就很快了。

“标记-清扫”所依据的思路同样是从堆栈和静态存储区出发,遍历所有的引用,进而找出所有存活的对象。每当它找到一个对象,就会给对象设一个标记,这个过程中不会回收任何对象。只有全部标记工作完成的时候,清理动作才会开始。在清理过程中,没有标记的对象将被释放,不会发生复制动作。所以剩下的堆空间是不连续的,垃圾回收器要是希望得到连续的空间的话,就得重新整理剩下的对象。

如前文所述,在这里所讨论的Java虚拟机中,内存分配以比较大的“块”为单位。如果对象比较大,它会占用单独的块。严格来说,停止-复制要求在释放旧的对象之前,必须先把所有存活对象从旧堆复制到新堆,这将导致大量内存复制行为。有了“块”之后,垃圾回收器在回收的时候就可以往废弃的块里拷贝对象了。每个快都用相应的代数来记录它是否还存活。通常,如果快在某处被引用,其代数会增加;垃圾回收器将对上次回收动作之后新分配的快进行整理。这对处理大量短命的临时对象很有帮助。垃圾回收器会定期进行完整的清理动作--大型对象仍然不会被复制(只是其代数会增加),内含小型对象的那些快则被复制并整理。Java虚拟机会进行监视,如果所有对象都很稳定,垃圾回收器的效率降低的话,就会切换到标记-清扫方式;同样,Java虚拟机会跟踪标记-清扫的效果,要是堆空间出现很多碎片,就会切换回停止-复制方式。这就是“自适应”技术。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  垃圾 回收