JVM学习笔记之四 四种引用和垃圾回收的两次标记

四种引用和两次标记

四种引用

    java中的数据类型我们知道是分为基本数据类型和引用类型的。基本数据类型是8种,分别是boolean byte short int long double float char,基本数据类型其变量内存中存储的是该变量的值,而引用类型在JDK 1.1中的描述是:如果Reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用。此定义下,一个对象只有被引用和没有被引用两种状态,这在使用中不够灵活方便。JDK1.2中对引用概念进行了扩充,细分为以下四种:

强引用 Strong Reference

    强引用就是类似“Object obj = new Object()”的引用,强引用永远不会被垃圾收集器回收。

软引用 Soft Reference

    用来描述一些还有用但是但是并非必须的对象。软引用关联的对象,在系统将要发生内存溢出之前,将会把这些对象列进回收范围之中进行第二次回收。如果回收后还是没有足够的内存,这会抛出OOM。很多系统缓存都会使用该类型的引用。

弱引用 WeakReference 

    也用来描述非必须对象,但是其强度比软引用弱,其关联的对象只能生存到下一次垃圾收集之前,当垃圾收集器开始回收内存时,无论内存是否够用,这些弱引用关联的对象都会被回收掉。

虚引用 PhantomReference

    也称幽灵引用或者幻影引用,是最弱的引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。设置虚引用的唯一目的就是能在这个对象被垃圾收集器回收时收到一个系统的通知。

两次标记

    一个对象从被判定为死亡对象到被垃圾收集器回收掉还要经历两次标记的过程,该过程可以认为是该对象在死刑的缓刑阶段。第一次标记:当可达性分析确认该对象没有引用链与GC Roots相连,则对其进行第一次标记和筛选,筛选的条件是重写了finalize()方法并没有执行过,对于重写了且并没有执行finalize()方法的对象这将其放置在一个F-Queue队列中,并在稍后由一个由虚拟机自动建立的低优先级的Finalizer线程去执行它。此处执行只保证执行该方法,但是不保证等待该方法执行结束,之所以这样子设计是为了系统的稳定性和健壮性考虑,以免该方法执行时间较长或者死循环导致系统崩溃。在此之后,系统会对对象进行第二次标记,如果在第一次标记之后的对象在执行finalize()方法时没有被引用到一个新的变量,这该对象将被回收掉。finalize方法只能被执行一次,并且一般不推荐也不建议重写Object的该方法,如果需要关闭外部资源,比如数据库,I/O等完全可在finally块中完成。以下是jdk中Object对象中finalize()方法的注释,部分做了翻译:


大意是:当垃圾收集判定一个对象没有引用指向它时,垃圾收集器会调用该方法。一个子类为了处理系统资源或者完成其他清理工作需要覆盖该方法。



    声明:本博客中大量参考引用了周志明作者《深入理解java虚拟机》2版中的第三章节的内容,也可以看作是本书的学习笔记。

猜你喜欢

转载自blog.csdn.net/tony_java_2017/article/details/80685148