关于java垃圾回收的理解,即gc,来源于 java编程思想 一书
垃圾回收的算法
-
引用计数法
引用计数法是一种简单但是速度很慢的回收计数,每个
对象都含有一个引用计数器,当有引用连接至对象时,引用计数器加一,当引用离开作用域或对象被置为null时,引用计数器减一,虽然引用计数器的开销不大,但是这个开销在正好程序的生命周期都存在,垃圾回收器会遍历全部的对象,发现某个对象的引用计数器为零时,就释放它占用的内存。但是这种方法存在缺陷,如果对象存在交叉循环引用,那么计数器永远不为0,就可能出现对象应该被回收,但是计数器不为零的情况,对垃圾回收器而言,定位这样的交叉循环引用所需的工作量也很大。引用计数法经常用来说明垃圾回收器的工作方式,但是似乎没有被用于java虚拟机的实现中。 -
引用追踪法
该方法主要思想是,任何存活的对象,都会在堆栈或者静态存储区找到他们的引用,如果从堆栈和静态存储区开始遍历所有引用,就能找到每一个活的对象,然后去追溯它的引用,直到所形成的网络全部被访问为止,那么剩下没有被访问的对象就是要被回收的对象,因为他们没有被任何对象引用或者没有引用任何其他对象。这种算法也不会出现交叉循环引用导致无法被回收的问题。 -
停止复制法(stop and copy)
该方法会暂停程序的运行,所以他不属于后台回收模式,然后将所有存活的对象从当前的堆复制到另一个堆,没有被复制的对象都是垃圾。这种方法效率比较低,因为需要两个堆的空间,还有就是程序进入稳定运行状态之后只会产生少量的垃圾,甚至没有垃圾,但是复制式回收器依然会把内存从两个堆之间复制,这样就很浪费。 -
标记清除法(mark and sweep)
该方法的思路依然是从堆栈和静态存储区出发,遍历所有的引用,进而找出存活的对象,每当它找到一个存活的对象时,都会给对象设置一个标记,此时不会进行回收,只有当全部标记完成时,清理才会开始,在清理过程中,未被标记的对象会被释放,释放之后的内存空间是不连续的,如果希望得到连续的空间,垃圾回收器还要继续整理。 -
分代收集法
分代收集法建立在停止复制法之上,停止复制法需要多块堆空间来复制对象,每个块都有相应的代数来记录它是否还存活,通常,如果块在某处被引用,其代数会增加。垃圾回收器进行回收时,如果对象被引用,不会发生复制,只会增加它的代数,未被引用的对象会被回收。