查找内存中不再使用的对象

  • 引用计数法

引用计数法就是如果一个对象没有被任何引用指向,则可视之为垃圾。这种方法的缺点就是不能检测到环的存在。

  • 2.根搜索算法

根搜索算法的基本思路就是通过一系列名为”GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。

引用计数法

下面通过一段代码来对比说明:

1
2
3
4
5
6
7
8
9
10
11
public class MyObject {
    public Object ref = null;
    public static void main(String[] args) {
        MyObject myObject1 = new MyObject();
        MyObject myObject2 = new MyObject();
        myObject1.ref = myObject2;
        myObject2.ref = myObject1;
        myObject1 = null;
        myObject2 = null;
    }
}

上述代码中myObject1和myObject2其实互相引用,他们的引用计数都为1,但是本身都是null,如果用引用计数法因为计数为1不会被GC回收,但他们本身为null,最终导致内存泄漏

如果采用的是引用计数算法:

再回到前面代码GcDemo的main方法共分为6个步骤:

  • Step1:GcObject实例1的引用计数加1,实例1的引用计数=1;
  • Step2:GcObject实例2的引用计数加1,实例2的引用计数=1;
  • Step3:GcObject实例2的引用计数再加1,实例2的引用计数=2;
  • Step4:GcObject实例1的引用计数再加1,实例1的引用计数=2;

执行到Step 4,则GcObject实例1和实例2的引用计数都等于2。

接下来继续结果图:

  • Step5:栈帧中obj1不再指向Java堆,GcObject实例1的引用计数减1,结果为1;
  • Step6:栈帧中obj2不再指向Java堆,GcObject实例2的引用计数减1,结果为1。

到此,发现GcObject实例1和实例2的计数引用都不为0,那么如果采用的引用计数算法的话,那么这两个实例所占的内存将得不到释放,这便产生了内存泄露。

 
根搜索算法
这是目前主流的虚拟机都是采用GC Roots Tracing算法,比如Sun的Hotspot虚拟机便是采用该算法。 该算法的核心算法是从GC Roots对象作为起始点,利用数学中图论知识,图中可达对象便是存活对象,而不可达对象则是需要回收的垃圾内存。这里涉及两个概念,一是GC Roots,一是可达性。

那么可以作为GC Roots的对象(见下图):

  • 虚拟机栈的栈帧的局部变量表所引用的对象;
  • 本地方法栈的JNI所引用的对象;
  • 方法区的静态变量和常量所引用的对象;

关于可达性的对象,便是能与GC Roots构成连通图的对象,如下图:

从上图,reference1、reference2、reference3都是GC Roots,可以看出:

  • reference1-> 对象实例1;
  • reference2-> 对象实例2;
  • reference3-> 对象实例4;
  • reference3-> 对象实例4 -> 对象实例6;

可以得出对象实例1、2、4、6都具有GC Roots可达性,也就是存活对象,不能被GC回收的对象。
而对于对象实例3、5直接虽然连通,但并没有任何一个GC Roots与之相连,这便是GC Roots不可达的对象,这就是GC需要回收的垃圾对象。

到这里,相信大家应该能彻底明白引用计数算法和根搜索算法的区别吧

再回过头来看看最前面的实例,GcObject实例1和实例2虽然从引用计数虽然都不为0,但从根搜索算法来看,都是GC Roots不可达的对象。

总之,对于对象之间循环引用的情况,引用计数算法,则GC无法回收这两个对象,而根搜索算法则可以正确回收。

【JVM底层策略 一】GC roots如何判断对象不可达的更多相关文章

  1. JVM高级特性-三、垃圾收集之判断对象存活算法

    一.概述 运行时数据区中,程序计数器.虚拟机栈.本地方法栈都是随线程而生随线程而灭的 因此,他们的内存分配和回收是确定的,在方法或线程结束时就回收.而Java堆和方 法区则是不确定的,程序运行过程中创 ...

  2. JVM 垃圾回收GC Roots Tracing

    1.跟搜索算法: JVM中对内存进行回收时,需要判断对象是否仍在使用中,可以通过GC Roots Tracing辨别. 定义: 通过一系列名为”GCRoots”的对象作为起始点,从这个节点向下搜索,搜 ...

  3. JVM的分区+查看GC对象是否存活+3种GC算法+7种垃圾收集器+如何减少GC次数

    一.JVM的分区:   1.程序计数器(私有) 程序计数器是一块较小的内存分区,你可以把它看做当前线程所执行的字节码的指示器. 在虚拟机的概念模型里,字节码解释器工作时,就是通过改变计数器的值来选择下 ...

  4. JVM垃圾回收(GC)

    JVM垃圾回收(GC) 1. 判断对象是否可以被回收 引用计数法:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收.此方法简单,但无法解决对象相互循环引用的问 ...

  5. Gc如何判断对象可以被回收?

    Gc如何判断对象可以被回收? 1 引用计数器 引用计数法的算法思路:给对象增加一个引用计数器,每当对象增加一个引用计数器+1,失去一个引用-1,所以当计数器是0的时候对象就没有引用了,就会被认为可回收 ...

  6. gc roots 垃圾回收

    gc roots包括以下几个: 虚拟机栈(栈桢中的本地变量表)中的引用对象 方法区中的类静态属性引用的对象 方法区中的常量引用的对象 本地方法栈中JNI(即native方法)的引用的对象 java,c ...

  7. GC是如何判断一个对象为"垃圾"的?被GC判断为"垃圾"的对象一定会被回收吗?

    一.GC如何判断一个对象为”垃圾”的java堆内存中存放着几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”.那么GC具体通过什么手段来 ...

  8. JVM如何判断对象能否被回收

    •写在前面说起Java和C++,很容易想到让人疯狂的指针,Java使用了内存动态分配和垃圾回收技术,让我们从C++的各种指针问题中摆脱出来,更加专心于业务逻辑,不过如果我们需要深入了解java的JVM ...

  9. 深入理解JVM(③)判断对象是否还健在?

    前言 因为Java对象主要存放在Java堆里,所以垃圾收集器(Garbage Collection)在对Java堆进行回收前,第一件事情就是要确定这些对象之中哪些还"存活"着,哪些 ...

随机推荐

  1. (转)Web.config配置文件详解

    花了点时间整理了一下ASP.NET Web.config配置文件的基本使用方法.很适合新手参看,由于Web.config在使用很灵活,可以自定义一些节点.所以这里只介绍一些比较常用的节点. <? ...

  2. JAVA学习笔记系列1-Java版本介绍

    JavaSE(Java Standard Edition):标准版,定位在个人计算机上的应用(桌面应用).因为一般都是Windows系统,因此Java的这个发展并不好. JavaEE(Java Ent ...

  3. java面向对象编程(三)--this

    看一段代码:(Demo112.java),先了解为什么要使用this. /* this的必要性 */ public class Demo112{ public static void main(Str ...

  4. java学习笔记41(数据库连接池 C3p0连接池)

    在之前的学习中,我们发现,我们需要频繁的创建连接对象,用完之后还需要在关闭资源,因为这些连接对象都是占资源的,但是又不得不创建,比较繁琐,为了解决这种情况,Java出现了数据库连接池: 数据库连接池的 ...

  5. Vue+WebSocket 实现页面实时刷新长连接

    最近vue项目要做数据实时刷新,折线图每秒重画一次,数据每0.5秒刷新一次,说白了就是实时刷新,因为数据量较大,用定时器估计页面停留一会就会卡死... 与后台人员讨论过后决定使用h5新增的WebSoc ...

  6. Power BI Desktop 新年快乐!

    新年快乐 2018年是Power BI 多产的一年!更新发布的功能就超过150多个,真是相当的强大! 为了庆祝这一成功的一年,Power BI官方团队制作了一个有趣的视频,展示他们对2018年最喜欢的 ...

  7. VS2008 快捷键大全

    转载自 https://www.cnblogs.com/likebeta/archive/2013/02/20/2919224.html Ctrl+E,D ----             格式化全部 ...

  8. 条件分支语句(SWICH语句)

    语法 swich(条件表达式){ Case 表达式: 语句……. Break; Case 表达式: 语句……. Break; Case 表达式: 语句……. Break; default: 语句……. ...

  9. SP四种作用范围pageContext、request、session、application 一看就懂

      作用域规定的是变量的有效期限: 1.如果把变量放到pageContext里,就说明它的作用域是page,它的有效范围只在当前jsp页面里. 从把变量放到pageContext开始,到jsp页面结束 ...

  10. 磁盘操作系统 cmd命令

    DOS CMD :磁盘操作系统 不区分大小写 **cd \ 根目录 cls 清空屏幕 dir 显示目录 d: 进入D盘 cd 进入目录命令 dir 查看当前目录的文件与目录 del 删除文件 del ...