一、引用计数器
引用计数是一种简单但速度很慢的垃圾回收技术。
创建的每一个对象都有一个与之相关联的引用计数器,当引用连接至这个对象时,引用计数加1。当引用离开作用域或者被置为null时,引用计数减1。管理引用计数的开销在整个程序生命中持续发生。垃圾回收器会站在含有全部对象的列表上遍历,当发现某个对象的引用计数为0 时,就会释放其占用的空间,但是,引用计数器模式经常会在计数数值变为0时立即释放对象。
缺陷:如果对象之间存在引用,可能会出现“对象应该被回收,但引用计数不等于0”的情况。对垃圾回收器而言,定位这样的交叉自引用的对象组所需的工作量极大,引用计数器常用来说明垃圾收集的工作方式。
二、自适应的垃圾回收技术
思想:对任何“活”的对象,一定能最终追溯到其存活在堆栈或者静态区的引用。如果从堆栈和静态存储去区开始,遍历所有的引用,就能找到所有的存活对象,对于发现的每个引用,必须追踪他所引用的对象,然后是此对象包含的所有引用,反复进行,知道“根源于堆栈和静态存储区的引用”所形成的的网络全部被访问为止。这解决了交互自引用的对象组的问题。
如何找到存活对象:(取决于不同java虚拟机的实现)
①停止--复制 stop-and-copy:先暂停运行中的程序,然后将所有存活对象从当前对堆复制到另一个堆,没有被复制的全是垃圾。当对象被复制到新堆时,他们是一个挨着一个的,所以新堆保持紧凑排序,然后就可以按照前述方法简单、直接的分配新空间。 当把对象从一处搬到另一处时,所有指向他的应用都必须修正。位于堆或者静态存储区的引用可以直接被修正。,但可能还有其他指向这些对象的引用,他们在遍历的过程中才能被找到。
缺点:效率降低, Ⅰ需要两个堆,然后在这两个堆之间来回倒腾,从而维护的空间增加一倍。 Ⅱ 复制浪费。程序进入稳定之后,可能只会产生少量的垃圾,甚至没有垃圾,尽管如此,这种复制式回收器仍然会将所内来回复制。
为了避免上述情况,一些java虚拟机会进行检查:要是没有新垃圾产生,就会转到另一种工作模式
②标记--清扫:速度慢,但是当只会产生少量垃圾甚至不产生垃圾时,他的速度就很快
从堆栈和静态存储区出发,遍历所有引用,进而找出获得对象。当他找到存活的对象的时候,就会给对象设置一个标记,在这个过程中不会回收人和对象,不会发生复制动作。当标记工作完成时,清理动作才会开始。在清理过程中。没有被标记的对象将被释放。不会发生任何复制动作。所以剩下的 堆空间是不连续的,垃圾回收器想要得到连续空间的话,就要重新整理剩下的对象。