莎士比亚说过:生存还是死亡这是一个问题?我们在进行JVM语言进行编程不需要考虑内存释放问题,因为JVM会帮助我们进行GC(垃圾回收),如此说来,JVM是如何判断对象的生存与死亡,哪些内存需要进行回收。在学习JVM垃圾回收之前,我们必须了解JVM如何判断对象的生存与死亡。
一. 判断方法
Java堆中几乎存放着Java世界中所有对象实例,垃圾收集器在对堆进行回收之前,第一件事请就是确定对象的存活与死亡。现阶段有以下两种主流方法判断。
1. 引用计数法
给每个对象添加一个引用计数器,对象被引用则+1,引用失效-1。任何时刻计数器为0的对象都是不可能再被使用的。它实现简单,判定效率高,但是Java语言没有使用,其中最主要原因是很难解决对象之间的相互循环引用问题。例如:ObjectA.instance = ObjectB; ObjectB.instance = ObjectA;除此之外,两个对象再无任何引用,实际上两个对象都不可能再被访问,但是它们互相引用着对方,导致它们的引用计数都不为0,于是GC算法无法对它们进行回收。
2. GC Root Tracing
主流商业应用程序语言(java,C#)都使用该算法。基本思路是通过一系列名为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链,则证明这个对象是不可用的。
在Java语言中,可以作为GC roots的对象包括:
- 虚拟机栈(栈帧中的本地变量表)中的引用对象
- 方法区中的类静态变量属性的引用对象
- 方法区中常量引用对象
- 本地方法栈中JNI(Java Native Interface)的引用对象
- 强引用:指程序代码普遍存在的,比如 A a = new A( );只要强引用还存在,GC不会回收掉被引用对象。
- 软引用:描述一些还有用的,但是并非必须的对象。在系统将要发生内存溢出异常前,会把这些对象列入回收范围,进行二次型回收,如果内存依旧不够,会抛出内存溢出异常。JDK提供softReference类来进行实现
- 弱引用:表述非必须对象,强度比软引用弱。只能生存到下次GC之前,此时无论内存是否足够都会被回收。JDK提供WeakReference类来实现。
- 虚引用:所有引用中最弱的一种引用关系,一个对象是否存在虚引用,不会对其生存时间构成影响,也不会通过虚引用来取得一个对象的实例。