Java垃圾回收机制-可达性分析算法解析

  • 前言
  • 一、可达性分析
  • 二、结果分析
  • 三、如何减少OOM概率


前言

Java回收机制是什么?可达性分析算法,可达性分析算法最重要的就是要先知道哪些对象死了,怎么知道对象已经死了呢,就要找到GCRoot对象,然后顺着引用路径一直找下去,如果GCRoot下面没有对象引用链,那么这些对象就可以认为是濒临死亡状态,等着垃圾回收器回收了。那么哪些对象是GCRoot对象,这个是关键,所以先要搞清楚GC Roots对象包含哪些,下面我来给大家通过GC Roots的对象定义,以及代码示例来简单理解一下java中GC是如何判断对象存活的。

一、可达性分析

在java中,作为GC Roots的对象包括

  1. 方法区:类静态属性的对象
  2. 方法区:常量的对象
  3. 虚拟机栈(本地变量表)中的对象
  4. 本地方法栈JNI(Native)中的对象
public class GCRootsTest {
   /**
     * 可达性分析算法
     */
    Object o =new Object();
    static Object GCRoot1 =new Object(); //GC Roots
    final  static Object GCRoot2 =new Object();//GC Roots
    public void haveGCRootMethod() {
        //可达
        Object object1 = GCRoot1; //=不是赋值,在对象中是引用,传递的是右边对象的地址
        Object object2 = object1;
        Object object3 = object1;
        Object object4 = object3;
    }
    public void notGCRootMethod(){
        //不可达(方法运行完后可回收)
        Object object5 = o;//o不是GCRoots
        Object object6 = object5;
        Object object7 = object5;
    }
    //本地变量表中引用的对象
    public void stack(){
        Object ostack =new Object();    //本地变量表的对象
        Object object8 = ostack;
        //以上object8 在方法没有(运行完)出栈前都是可达的
    }
 }

参考示意图:

java GCroot可达性分析 java 可达性分析算法_可达性

二、结果分析

haveGCRootMethod方法中:

static Object GCRoot1 =new Object(); //GC Roots
    final  static Object GCRoot2 =new Object();//GC Roots
这两段代码的属性声明,分别是静态和常量,均在方法区中,所以是GC Roots节点,我们找到了GCRoot节点,随后object1、object2、object3、object4依次引用GCRoot1节点,自然形成图中的一条引用链,所以这几个对象都是活着的,不会被垃圾回收器回收。

notGCRootMethod方法中:
首先,要知道类中声明的代码段o不是GCRoot对象

Object o =new Object();

o这个对象在哪呢,它不在GCRoots区域,它在区域外面,我忘记画了o
当notGCRootMethod方法执行过程中,object5、object6、object7均在GCRoot区域中,但是object5引用了非GCRoots区域的o对象,指向o,随着方法运行结束,那么object5、object6、object7将会移出GCRoots区域,这个时候就是你看见图中所在的位置,接着,等着被垃圾回收器回收。

stack方法中:
是本地变量表中引用的对象,在方法没有执行结束之前,object8都是可达的,并且引用ostack对象,存在GCRoots区域中,但是当方法结束以后,就会像上图那样移出GCRoots区域,等着被垃圾回收器回收

三、如何减少OOM概率

  1. 尽可能少的发生内存泄露
  2. 尽可能不在循环中申请内存
  3. 尽可能不在调用次数多的函数申请内存