深入理解Java虚拟机——对象的引用和回收

223 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

四种引用类型

引用有四种,从强到弱依次为强引用、软引用、弱引用和虚引用。

  • 强引用是代码中普遍存在的引用赋值,例如Object obj = new Object()这种引用关系,任何情况下只要强引用关系存在,垃圾收集器就不会回收掉对象。
  • 软引用是描述有用但非必须的对象,在系统发生内存溢出异常前会回收软引用,如果回收后还没有足够内存才会抛出内存溢出异常。
  • 弱引用同样描述有用但非必须的对象,它的强度弱于软引用,这些对象仅能存活到下一次垃圾收集前。
  • 虚引用是最弱的引用关系,不会对对象的生存时间构成影响,也无法通过虚引用获得对象实例,虚引用的唯一作用是在对象被垃圾收集时收到一个系统通知。

对象回收前的操作

当对象被判定为“不可达对象”后,首先判断该对象是否需要执行finalize()方法,如果对象没有重写该方法或者已经被虚拟机调用过,那么就不会执行。 如果需要执行finalize()方法,会把对象放到F-Queue队列中,由虚拟机建立的Finalizer线程执行对象的finialize()方法。

对象可以通过重写finalize()方法进行自我拯救,只需要在方法中将自己关联到引用链上,就在收集器对F-Queue进行标记时会被移出回收集合。

方法区的回收

方法区的垃圾收集性价比比较低,每次回收的空间很有限。 方法区的垃圾收集主要回收“废弃的常量”和“不再使用的类型”两种,对于废弃常量主要看是否还有字符串对象引用这个常量,对于类是否回收需要看类是否满足下面三个条件:

  1. 类的所有实例都被回收,即堆中不存在该类及派生类的实例。
  2. 类的加载器被回收。
  3. 该类的Class对象没有被引用,也无法通过反射进行访问。