Java中单例对象不会被GC回收

  hotspot虚拟机的垃圾收集算法使用根搜索算法。这个算法的基本思路是:对任何“活”的对象,必定能最终追溯到其存活在堆栈或静态存储区之中的引用。经过一系列名为根(GC Roots)的引用做为起点,从这些根开始搜索,通过一系列的路径,若是能够到达java堆中的对象,那么这个对象就是“活”的,是不可回收的。能够做为根的对象有:java

  • 虚拟机栈(栈桢中的本地变量表)中的引用的对象。
  • 方法区中的类静态属性引用的对象。
  • 方法区中的常量引用的对象。
  • 本地方法栈中JNI的引用的对象。

     方法区是jvm的一块内存区域,用来存放类相关的信息。很明显,java中单例模式建立的对象被本身类中的静态属性所引用,符合第二条,所以,单例对象不会被jvm垃圾收集。算法

            虽然jvm堆中的单例对象不会被垃圾收集,可是单例类自己若是长时间不用会不会被收集呢?由于jvm对方法区也是有垃圾收集机制的。若是单例类被收集,那么堆中的对象就会失去到根的路径,必然会被垃圾收集掉。对此,笔者查阅了hotspot虚拟机对方法区的垃圾收集方法,jvm卸载类的断定条件以下:jvm

    • 该类全部的实例都已经被回收,也就是java堆中不存在该类的任何实例。
    • 加载该类的ClassLoader已经被回收。
    • 该类对应的java.lang.Class对象没有任何地方被引用,没法在任何地方经过反射访问该类的方法。

            只有三个条件都知足,jvm才会在垃圾收集的时候卸载类。显然,单例的类不知足条件一,所以单例类也不会被卸载。也就是说,只要单例类中的静态引用指向jvm堆中的单例对象,那么单例类和单例对象都不会被垃圾收集,依据根搜索算法,对象是否会被垃圾收集与未被使用时间长短无关,仅仅在于这个对象是否是“活”的。对象

相关文章
相关标签/搜索