3.2 对象已死?
3.2.2 可达性分析算法
通过一系列“GC Roots”根对象作为起始节点集,从这些结点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”,如果某个对象到GC Roots间没有任何引用链相连则证明此对象是不可能再被使用的
固定可作为GC Roots对象包括以下几种:
- 在虚拟机栈中引用的对象
- 在方法区中类静态属性引用的对象
- 在方法区中常量引用的对象
- 在本地方法栈中JNI(Native方法)引用的对象
- Java虚拟机内部的引用
- 所以被同步锁持有的对象
反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等
3.2.3 再谈引用
强引用、软引用、弱引用和虚引用
- 强引用时最传统的“引用”的定义,指在程序代码之间普遍存在的引用赋值,无论什么情况下,只要强引用关系存在,垃圾收集器就永远无法回收掉被引用的对象
- 软引用时用来描述一些还有用,但非必须的对象。只被软引用关联着的对象,在系统将要发生内存溢出前,会把这些对象列进回收范围之中进行二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常
- 弱引用:用来描述那些非必须对象,但是它的强度比软引用还要更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生为止
虚引用:最弱的一种引用关系,唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知
3.2.4 生存还是死亡?
GC要回收一个对象至少要经历两次标记过程,第一次是对象进行可达性分析判断为与GC root不可达时,随后是进行一次筛选,筛选的条件是此对象是否有必要要执行finalize()方法
如果该对象有必要执行finalize()方法,则会将该对象放在一个F-Queue的对列中,并由虚拟机自动建立的、低调度优先级的Finalizer线程去执行他们的finalize()方法。
第二次回收是收集器对F-Queue中的对象进行标记,如果对象要拯救自己,只要重新与引用链上的任何一个对象建立关联即可
任何一个对象的finalize方法只能被系统调用一次
建议忘掉finalize方法,因为可以用try-finally替代3.2.5 回收方法区
方法区的垃圾收集主要回收两部分内容:废弃的常量和不再使用的类型
判断一个常量是否废弃,只需要看虚拟机中有没有其他地方引用这个常量
判断一个类型是“不再使用的类”,需要满足三个条件该类所有的实例都已经被回收
- 加载该类的类加载器都已经被回收,一般很难达成这个条件
- 该类对应的class对象没有在任何地方被引用
3.3 垃圾收集算法