大家好,今天来介绍Java虚拟机判断对象是否存活使用的算法:可达性分析算法。
1、可达性分析算法介绍:
根据"GC Roots"的根对象作为起始节点集合,从这些根节点开始,根据引用关系向下搜素,搜索过程引用的路径为"引用链"。如果某一对象到GC Root间没有任何引用链相连,则该对象为不可达对象,被视为可回收对象。
如图:
2、Java虚拟机中固定可作为GC Roots的对象:
- 在虚拟机栈(栈帧中的本地变量表)中引用的对象,例:各个线程被调用的方法堆栈中使用到的参数,局部变量、临时变量等,代码示例见下图:
public class Test1 { public static void main(String[] args) { Test1 test1 = new Test1(); } }
如上图代码示例中,test1是栈帧中本地变量,test1为虚拟机栈所引用的对象,可作为GC Roots根对象。
- 在方法区类静态属性引用的对象,比如Java类的引用类型的静态变量,代码见下图:
public class Test2 { static Test1 test1 ; public static void main(String[] args) { test1 = new Test1(); } }
- 在方法区中常量引用的对象,比如字符串常量池里的引用,代码示例见下图:
public class Test3 { static final Test1 test1 = new Test1() ; public static void main(String[] args) { System.out.println(test1); } }
- 在本地方法栈中JNI(Native方法)引用的对象
- 反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等
3、无论是通过引用计数法判断对象的引用数量,还是通过可达性分析算法判断对象是否引用链可达,都和“引用”离不开关系。
引用的概念:如果针对某一块区域发起垃圾收集时(如最典型的只针对新生代的垃圾收集),必须考虑到内存区域是虚拟机自己的实现细节,更不是孤立封闭的,所以某个区域内的对象完全有可能被位于堆中其他区域的对象所引用,需要将关联区域的对象一并加入GC Roots集合中。
引用分为以下四种:
- 强引用:对对象进行直接引用,"Object obj = new Object()"这种引用关系,无论任何情况下,只要强引用关系还在,垃圾收集器就永远不会回收掉被引用的对象
- 软引用:如果一个对象只具有软引用,并且当前虚拟机的内存足够,那么它就不会被垃圾回收器回收,否则就会回收软引用对象
- 弱引用:用来描述非必须对象,强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生为止
- 虚引用:它是最弱的一种引用关系,为一个对象设置虚引用关联的唯一目的就是为了能在这个对象被收集器回收时收到一个系统通知
接下来的文章中会对引用详细分析,后面就进入到垃圾回收算法的介绍。