判断对象是否存活算法:

  • 引用计数算法:对象中添加一个引用计数器,每当有一个地方引用时,计数器值就加1;引用失效时,计数器值就减1;计数器为0的对象就是不再被使用的。

      缺点:java虚拟机不使用其管理内存原因是它很难解决对象之间相互循环引用的问题

  • 可达性分析算法(java,c#):通过一系列称为gc roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到gc roots没有任何引用链相连时,则此对象不可用。jvm-----垃圾对象回收过程

可作为gc roots的对象:虚拟机栈中引用的对象、方法区中类静态属性引用的对象、方法区中类常量引用的对象、本地方法栈中jni(即一般所说的native方法)引用的对象。

-----------------------------------------------------------------------------------
java对象引用类型:强引用、软引用、弱引用、虚引用。

  • 强引用:代码中普遍存在的,类似Object obj = new Object(),只要强引用存在,垃圾收集器永远不会回收被引用的对象
  • 软引用:描述一些还有用但并非必须的对象。在系统将要发生内存溢出异常之前,将会把软引用对象进行回收,若回收后仍没有足够内存才会抛出内存溢出异常(通过SoftReference类实现软引用)
  • 弱引用:强度比软引用更弱。被弱引用关联的对象只能生存到下一次垃圾收集发生之前。当垃圾收集工作开始时,无论内存是否足够,都会将其回收。(通过WeakReference类实现弱引用)
  • 虚引用/幽灵引用/幻影引用:最弱的一种引用关系。不会对对象生存时间构成影响,也无法通过虚引用来取得对象实例。设置虚引用的唯一目的就是在对象被收集器回收时收到一个系统通知(通过PhantomReference类实现虚引用)

-----------------------------------------------------------------------------------

垃圾对象被回收过程:在可达性分析算法中不可达的对象,并非被立即回收,而是要经过两次标记:

  • 对象是否覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,若未覆盖或者已调用则回收
  • 覆盖finalize()方法并且未被调用,则对象会放置在F-Queue队列中,并在稍后由一个虚拟机自动建立的、低优先级的Finalizer线程去触发finalize方法,但并不会等待它运行结束(原因是若finalizer执行缓慢或者死循环,则F-Queue队列其他对象处于永久等待,导致整个内存回收系统崩溃)。稍后gc将对F-Queue中的对象再次标记(只要重新与引用链上的任何一个对象建立关联,就被移除即将回收集合。否则进行回收)

!!!注意:

  1. finalize()方法只会被系统自动调用一次,如果对象面临下次回收,finalizer()方法不会被再次执行
  2. 尽量避免使用finalize()方法来拯救对象

相关文章: