JVM(四)——垃圾回收机制

来源:互联网 发布:大数据对旅游业的影响 编辑:程序博客网 时间:2024/04/30 14:41

垃圾收集(Garbage Collection, GC),需要完成三件事情:

    哪些内存需要回收?

    什么时候回收?

     如何回收?

对象已死?

      堆中存在着所有的对象实例,垃圾回收器在对堆进行回收之前,就要确定这些对象有哪些还“存活”着,哪些已经“死去”(即不可能再被任何途径使用的对象)。


1、引用计数法:

      为每个对象增加一个字段记录被引用的次数,并由运行时跟踪和更新引用的总数;缺陷:如果两个对象互相引用,这两个对象是永远不能通过引用计数法回收的。


2、根搜索法

      在主流的商用程序语言中(Java和C#,甚至包括前面提到的古老的Lisp),都是使用根搜索算法(GC Roots Tracing)判定对象是否存活的。这个算法的基本思路就是通过一系列的名为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(用图论的话来说就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。如图3-1所示,对象object 5、object 6、object 7虽然互相有关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收的对象。

      在Java语言里,可作为GC Roots的对象包括下面几种:

             虚拟机栈(栈帧中的本地变量表)中的引用的对象。

             方法区中的类静态属性引用的对象。

             方法区中的常量引用的对象。

             本地方法栈中JNI(即一般说的Native方法)的引用的对象。

垃圾回收算法

1、标记-清除算法

     标记—清除算法包括两个阶段:“标记”和“清除”。在标记阶段,确定所有要回收的对象,并做标记。清除阶段紧随标记阶段,将标记阶段确定不可用的对象清除。

      标记—清除算法是基础的收集算法,标记和清除阶段的效率不高,而且清除后回产生大量的不连续空间(碎片),这样当程序需要分配大内存对象时,可能无法找到足够的连续空间。

回收前:

 

回收后:

 

白色:表示未被使用

绿色:表示正在使用

蓝色:表示即将回收

2、复制算法

复制算法是把内存分成大小相等的两块,每次使用其中一块,当垃圾回收的时候,把存活的对象复制到另一块上,然后把这块内存整个清理掉。

复制算法实现简单,运行效率高,但是由于每次只能使用其中的一半,造成内存的利用率不高。现在的JVM用复制方法收集新生代,由于新生代中大部分对象(98%)都是朝生夕死的,所以两块内存的比例不是1:1(大概是8:1)。

回收前:

 

回收后:

 

3、标记整理算法

标记—整理算法和标记—清除算法一样,但是标记—整理算法不是把存活对象复制到另一块内存,而是把存活对象往内存的一端移动,然后直接回收边界以外的内存。

标记—整理算法提高了内存的利用率,并且它适合在收集对象存活时间较长的老年代。

回收前:

 

回收后:

 

4、分代收集算法

分代收集是根据对象的存活时间把内存分为新生代和老年代,根据个代对象的存活特点,每个代采用不同的垃圾回收算法。新生代采用标记—复制算法,老年代采用标记—整理算法。

 

垃圾回收器

 

0 0