什么情况下对象会被垃圾回收机制回收

什么时候会触发垃圾回收?

当内存不足时,会触发GC

如何判断一个对象是否能被回收

一般有两种方式

  • 引用计数法
  • 可达性分析算法

引用计数法

为每个对象添加一个引用计数器,对象被引用一次该计数器就+1,失去一次引用就-1,直到引用计数为0,表示该对象没有在任何地方被引用,那么这个对象就可以被回收了

但是在Java中没有使用这种方式,原因是该方式无法解决对象循环引用的情况,比如对象A引用了对象B,对象B又引用了对象A,但是对象A和对象B除此之外没有被任何其他对象引用,垃圾回收机制又不能回收它们

可达性分析算法

Java虚拟机采用的是这种算法,来判断一个对象是否能够被回收。

该算法通过一个引用链,加上GC Roots来看,如果从GC Roots开始到某个对象之间存在着一条引用链,那么该对象就是可达的,也就是不会被垃圾回收机制回收的对象,反之,则对象可以被回收

什么样的对象能够成为GC Roots

  • 局部变量,如public Object object = new Object(),object就是一个GC Roots
  • 静态变量,如public static DateTime dateTime = new DateTime(),dateTime就是一个GC Roots
  • 常量引用的对象
  • 被同步锁Synchronized持有的对象
  • 虚拟机栈、本地方法栈中引用的对象
  • 虚拟机内部的引用,如类加载器,OutOfMemoryError等常驻的异常对象
  • JMXBean、本地代码缓存等

Java中的引用

  • 强引用,永远不会被垃圾回收,如public Object object = new Object(),object就是一个强引用
  • 软引用,在发生OOM之前会被回收,类SoftReference可以用于实现软引用
  • 弱引用,在发生GC的时候会被回收,类WeakReference可以用于实现弱引用
  • 虚引用,随时都可能被回收

finalize()方法的作用

如果一个对象没有对应的GC Roots,那么当发生GC的时候,它也不一定会被回收。

你可以重写finalize()方法,在该方法中再给这个对象一个强引用

方法区的垃圾回收

方法区主要的回收对象为废弃常量及不再使用的类

  • 废弃常量:没有被任何地方引用的常量
  • 废弃类
    • 该类的所有实例都被回收
    • 该类没有在任何地方被引用
    • 加载该类的类加载器被回收