码迷,mamicode.com
首页 > 编程语言 > 详细

Java 垃圾回收机制(早期版本)

时间:2017-08-28 23:47:32      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:回收   虚拟   width   就会   分享   工作方式   完成   垃圾   工作   

Java 垃圾回收机制在我们普通理解来看,应该视为一种低优先级的后台进程来实现的,其实早期版本的Java虚拟机并非以这种方式实现的。

先从一种很简单的垃圾回收方式开始。

引用计数

  引用计数是一种简单但是速度很慢的垃圾回收技术。

  每个对象都含有要给引用计数器,当有引用连接至对象时,引用计数+1。

  当引用离开作用域或者被置为null时,引用计数-1。

  当发现某个对象的引用计数为0时,就释放其占用的空间。

  技术分享

    这种方法开销在整个程序生命周期中持续发生,并且该方法有个缺陷,如果对象之间存在循环引用,可能会出现  “对象应该被收回,但引用计数却不为零”  的情况。

    即

b.setA(a);
a.setB(b);

    对垃圾回收器而言,定位这样的交换自引用的对象组所需的工作量极大。引用计数常用来说明垃圾收集的工作方式,但似乎未被应用于任何一种Java虚拟机实现中。


 

如何解决

  很多垃圾回收器并非基于引用记数计数。它们依赖的思想是:

    对任何“活”对象,一定能最终追溯到其存活再堆栈或者静态存储区之中的引用。这个引用链条可能会穿过数个对象层次。由此,如果从堆栈和静态存储区开始,遍历所有的引用,就能找到所有“活”的对象。对于发现的每个引用,必须追踪它所引用的对象,然后是此对象包含的所有引用,如此反复进行,知道“根源于堆栈和静态存储区的引用”所形成的网络全部被访问为止。你所访问过的对象必须是“活”的。

    注意,这就解决“交互自引用的对象组”的问题——这种现象根本不会被发现,因此也被自动回收了。


 

停止-复制

   显然,意味着,这种方法要先暂停程序运行(所以他不属于后台回收模式),然后将所有存活的对象从当前堆栈复制到另个堆(所有指向它的引用都要被重新修正),没有被复制的全部都是垃圾。

   当对象被复制到新堆时,他们时一个挨着一个的,所以新堆保持紧凑配列,然后就可以根据前述方法,直接地分配新空间了。

 

   存在的问题:效率太低。

    (1)在两个堆之间倒腾,需要维护多一倍的空间;

    (2)程序进入稳定状态后,可能只产生少量垃圾,复制式回收器仍然会将所有内存自一处复制到另一处,这很浪费。

   为了解决第二个问题,产生了“标记-清扫”

 

标记-清扫

  从堆栈和静态存储出发,遍历所有引用,进而找出所有活的对象,并标记,整个过程不会回收任何对象。

  只有全部标记工作完成的时候,清理动作才会开始。在清理过程中,没有标记的对象将被释放,不会发生任何复制动作。

  但此方法同样必须在程序暂停的情况下才能进行。

 

  综合两种方法,即可形成早期Java回收机制——“自适应”技术

  顾名思义,Java虚拟机会进行监控,如果对象都很稳定,垃圾回收器的效率降低时,就切换“标记-清理”方式;

  同样,Java虚拟机会跟踪“标记-清理”的效果,要是堆空间出现很多碎片,就会切换回“停止-复制”方式。

 

 

    

  

 

Java 垃圾回收机制(早期版本)

标签:回收   虚拟   width   就会   分享   工作方式   完成   垃圾   工作   

原文地址:http://www.cnblogs.com/rekent/p/7442118.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!