3.2 对象已死?

3.2.2 可达性分析算法

通过一系列“GC Roots”根对象作为起始节点集,从这些结点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”,如果某个对象到GC Roots间没有任何引用链相连则证明此对象是不可能再被使用的
固定可作为GC Roots对象包括以下几种:

  • 在虚拟机栈中引用的对象
  • 在方法区中类静态属性引用的对象
  • 在方法区中常量引用的对象
  • 在本地方法栈中JNI(Native方法)引用的对象
  • Java虚拟机内部的引用
  • 所以被同步锁持有的对象
  • 反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等

    3.2.3 再谈引用

  • 强引用、软引用、弱引用和虚引用

  1. 强引用时最传统的“引用”的定义,指在程序代码之间普遍存在的引用赋值,无论什么情况下,只要强引用关系存在,垃圾收集器就永远无法回收掉被引用的对象
  2. 软引用时用来描述一些还有用,但非必须的对象。只被软引用关联着的对象,在系统将要发生内存溢出前,会把这些对象列进回收范围之中进行二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常
  3. 弱引用:用来描述那些非必须对象,但是它的强度比软引用还要更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生为止
  4. 虚引用:最弱的一种引用关系,唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知

    3.2.4 生存还是死亡?

    GC要回收一个对象至少要经历两次标记过程,第一次是对象进行可达性分析判断为与GC root不可达时,随后是进行一次筛选,筛选的条件是此对象是否有必要要执行finalize()方法
    如果该对象有必要执行finalize()方法,则会将该对象放在一个F-Queue的对列中,并由虚拟机自动建立的、低调度优先级的Finalizer线程去执行他们的finalize()方法。
    第二次回收是收集器对F-Queue中的对象进行标记,如果对象要拯救自己,只要重新与引用链上的任何一个对象建立关联即可
    任何一个对象的finalize方法只能被系统调用一次
    建议忘掉finalize方法,因为可以用try-finally替代

    3.2.5 回收方法区

    方法区的垃圾收集主要回收两部分内容:废弃的常量和不再使用的类型
    判断一个常量是否废弃,只需要看虚拟机中有没有其他地方引用这个常量
    判断一个类型是“不再使用的类”,需要满足三个条件

  5. 该类所有的实例都已经被回收

  6. 加载该类的类加载器都已经被回收,一般很难达成这个条件
  7. 该类对应的class对象没有在任何地方被引用

    3.3 垃圾收集算法