JVM判断对象是否存活之引用计数法、可达性分析

目录

前言

引用计数法

概念

优点

缺点

可达性分析

概念

缺点:

扩展:

1.GC Roots 概念

2.STW (Stop the world)

前言

JVM有两种算法来判断对象是否存活,分别是引用计数法和可达性分析算法,针对可达性分析算法STW时间长、内存消耗等问题下可依赖三色标记法解决。

引用计数法

JVM判断对象是否存活之引用计数法、可达性分析_第1张图片

概念

对象中添加一个计数器,每当有一个地方引用它,计数器就加 1;

如果引用失效,计数器就减 1;

任何时候计数器为 0 的对象就是不可能再被使用的。

优点

这个方法实现简单,效率高。

缺点

JVM判断对象是否存活之引用计数法、可达性分析_第2张图片

很难解决对象之间相互循环引用,循环引引用会导致对象无法被回收,最终会导致内存泄漏及内存溢出。

可达性分析

JVM判断对象是否存活之引用计数法、可达性分析_第3张图片

概念

通过一系列的称为GC根“的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到GC根没有任何引用链相连的话,则证明此对象是不可用的。

过程

要两次标记:
1.第一次标记通过可达性分析算法。如果没有GC Roots相连接的引用链,那么将第一次标记
2.如果对象的 finalize()方法被覆盖并且没有执行过,则放在F-Queue队列中等待执行(不一定会执行,如果一段时间后该队列的 finalize() 方法被执行且和GC Roots关联,则移出“即将回收集合。如果仍然没有关联,则进行第二次标记,才会对该对象进行回收

代码如下: 

public class TestGCRoot {
    public static void main(String[] args) throws IOException {
        List list = new ArrayList<>();
        list.add("a");
        list.add("b");
        System.out.println(1);
        System.in.read();

        list = null;
        System.out.println(2);
        System.in.read();
        System.out.println("end...");
    }
} 
  

 缺点:

1.STW时间长

2. 内存消耗严重

扩展:

1.GC Roots 概念

GC roots是作为可达性分析算法的起点的。要实现语正确的可达性分析,就必须要能完整枚举出所有的GCRoots,否则就可能会漏扫描应该存活的对象,导致GC错误回收了这些被漏扫的活对象。那么,所谓“GC就是一组必须活跃的引用。

JVM判断对象是否存活之引用计数法、可达性分析_第4张图片

可以当GC roots 引用链得:

Class - 由系统类加载器(system class loader)加载的对象,这些类是不能够被回收的,他们可以以静态字段的方式保存持有其它对象。
Thread - 活着的线程
Stack Local - Java方法的local变量或参数
JNI Local - JNI方法的local变量或参数
JNI Global - 全局JNII用
Monitor Used - 被同步锁 (synchronized) 持有的对象

2.SWT (Stop the world)

Java中Stop-The-World机制简称STW,是在执行垃圾收集算法时,Java应用程序的其他所有线程都被挂起,这是Java中一种全局暂停现象,全局停顿,所有Java代码停止,native代码可以执行,但不能与JVM交互

JVM判断对象是否存活之引用计数法、可达性分析_第5张图片

STW产生的问题: 

用户线程的运行必然会导致对象的引用关系发生改变,这就会导致两种情况:

多标: 其实就是这个对象原本应该被回收掉的垃圾对象,但是被错误的标记成了存活对象从而导致这个对象没有被GC回收掉。产生了一些浮动垃圾,下次GC再清理就可以
漏标:一个对象本来应该是存活对象,但是没有被正确的标记上,导致被错误的垃圾回收掉了

你可能感兴趣的:(jvm)