Java虚拟机详解----JVM常见问题总结 (3)

  给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。

但是:

  主流的java虚拟机并没有选用引用计数算法来管理内存,其中最主要的原因是:它很难解决对象之间相互循环引用的问题

优点:

  算法的实现简单,判定效率也高,大部分情况下是一个不错的算法。很多地方应用到它

缺点:

引用和去引用伴随加法和减法,影响性能

致命的缺陷:对于循环引用的对象无法进行回收

2、根搜索算法(jvm采用的算法)

概念:

  设立若干种根对象,当任何一个根对象(GC Root)到某一个对象均不可达时,则认为这个对象是可以被回收的

注:这里提到,设立若干种根对象,当任何一个根对象到某一个对象均不可达时,则认为这个对象是可以被回收的。我们在后面介绍标记-清理算法/标记整理算法时,也会一直强调从根节点开始,对所有可达对象做一次标记,那什么叫做可达呢?

可达性分析:

  从根(GC Roots)的对象作为起始点,开始向下搜索,搜索所走过的路径称为“引用链”,当一个对象到GC Roots没有任何引用链相连(用图论的概念来讲,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。

83fbdb3a-6da2-4307-9cc5-63663080c2ce

如上图所示,ObjectD和ObjectE是互相关联的,但是由于GC roots到这两个对象不可达,所以最终D和E还是会被当做GC的对象,上图若是采用引用计数法,则A-E五个对象都不会被回收。

根(GC Roots):

说到GC roots(GC根),在JAVA语言中,可以当做GC roots的对象有以下几种:

1、(栈帧中的本地变量表)中引用的对象

2、方法区中的静态成员。

3、方法区中的常量引用的对象(全局变量)

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

注:第一和第四种都是指的方法的本地变量表,第二种表达的意思比较清晰,第三种主要指的是声明为final的常量值。

在根搜索算法的基础上,现代虚拟机的实现当中,垃圾搜集的算法主要有三种,分别是标记-清除算法复制算法标记-整理算法。这三种算法都扩充了根搜索算法,不过它们理解起来还是非常好理解的。

五、垃圾回收算法:

1、标记-清除算法:

概念:

标记阶段:先通过根节点,标记所有从根节点开始的可达对象。因此,未被标记的对象就是未被引用的垃圾对象;

清除阶段:清除所有未被标记的对象。

缺点:

标记和清除的过程效率不高(标记和清除都需要从头遍历到尾)

标记清除后会产生大量不连续的碎片

2、复制算法:(新生代的GC)

概念:

  将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,然后清除正在使用的内存块中的所有对象。

优点:

这样使得每次都是对整个半区进行回收,内存分配时也就不用考虑内存碎片等情况

只要移动堆顶指针,按顺序分配内存即可,实现简单,运行效率高

缺点:空间的浪费

  从以上描述不难看出,复制算法要想使用,最起码对象的存活率要非常低才行。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzjwyz.html