Java垃圾回收机制(一)

来源:互联网 发布:windows动画不流畅 编辑:程序博客网 时间:2024/04/30 12:16
    在堆里面存放着Java中几乎所有的对象实例,垃圾收集器在对堆进行回收前,首先就是确定这些对象中哪些还是“存活”,哪些已经“死亡”(即不可能再被任何途径使用的对象)。

1、判断对象是否存活的算法:引用计数法和可达性分析算法

   引用计数法: 给对象中添加一个引用计数器,每当有一个对方引用它时,计数器值就加1 ;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。   可达性分析算法:通过一系列的称为“GC Roots(根集)”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到根集没有任何引用链相连时,则证明此对象是不可用的。

2、垃圾回收机制的意义

    在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾。虚拟机的一个系统级线程会自动释放该内存块。垃圾回收意味着程序不再需要的对象是“无用信息”,这些信息将被丢弃。当一个对象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用,事实上,除了释放没用的对象,垃圾回收也可以清除内存记录碎片。由于创建对象 和垃圾回收器释放丢弃对象所占的内存空间,内存会出现碎片。碎片是分配给对象的内存块之间的空闲内存洞。碎片整理将所占用的堆内存移到堆得一端,jvm将整理出的内存分配给新的对象。    垃圾回收能自动释放内存空间,减轻编程的负担,不用考虑难懂的存储器问题,大大缩短时间,其次是保护了程序的完整性局限性:    1.它的开销影响程序性能,Java虚拟机必须追踪运行程序中有用的对象,而且最终释放没用的对象,这个过程需要消耗时间。    2.垃圾回收算法的不完备性,采用的某些垃圾回收算法就不能保证百分之百收集到所有的废弃内存。

3、垃圾收集算法

3.1 标记-清除算法(Mark-Sweep)
算法分为“标记”和“清除”两个阶段:首先标记出所有需要被回收的对象,在标记完成后统一回收所有被标记的对象。
局限性:
1.效率问题:标记和清除两个过程的效率都不高
2.空间问题:标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
3.2 复制算法(Copying)
为了解决效率问题,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对整个半区进行内存回收,内存分配是也就不用考虑内存碎片等复杂问题了,只要移动堆顶指针,按顺序分配内存即可。
缺点:收集器必须复制所有的活动对象,这增加了程序等待时间。
3.3 标记-整理算法
适用于老年代的特点,标记过程仍然与“标记-清除”算法一样,但后续步骤不是对回收对象直接清理,而是让存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
3.4 分代收集算法
根据对象存活周期的不同将内存划分为几块,一般分为新生代和老年代
新生代:每次垃圾回收时都发现有大批对象死去,只有少量存活,选用复制算法;
老年代:对象存活率高,没有额外空间进行分配担保,就必须使用“标记-清理”或者标记-整理“标记-整理”算法来进行回收。

0 0