垃圾回收的实质就是去释放不再被使用对象的内存。
那么就要通过特定的方法去寻找判定哪些对象不再被引用了。

回收预处理(预标记哪些对象可以被回收)

引用计数算法

对对象添加一个引用计数器,每当一个地方引用到该对象时,就对计数器加1。当引用失效的时候就减1。当对象的计数器为0的时候,任何地方都不能被使用了。
该方法实现简单,同时判定效率也很高。在游戏脚本中,python中都被广泛应用,主要是做内存的管理。但是在jvm中并没有用这种方法去判定对象,因为在java中会存在循环依赖的场景,这时就会出现两个对象的引用最少也是1的情况,那么遇到这种方法就捉襟见肘了。

可达性算法分析⭐

通过一系列的“GCRoot”的对象作为起始点,从这些节点开始向下搜索,搜所走过的路径称为引用链,当一个对象到GCRoots没有任何引用链相连时,则证明这个对象是不可用的。下图中Object_E就是一个不可用对象,包括F,G也同样不可用。因为F,G连接到了E,而E并没有和GCRoot相连接因此它们也是不可用的。
image.png

可以成为GCRoot的对象:

虚拟机栈中引用的对象

java会将局部变量都加载进局部变量表中。在JVM规范中,局部变量就是可以作为GC Roots的
image.png

image.png

静态属性引用的对象

在方法区存在对示例对象的引用的时候也可以看做是一种GC Roots,此时只要一个对象被GC Roots引用了,就不会去回收他。
image.png
image.png

本地方法栈中的JNI(本地方法)引用的对象

引用⭐

引用存在以下几类, 强引用(Strong Reference) 、 软引用(Soft Reference) 、 弱引用(Weak Reference) 和 虚引
用(Phantom Reference),它们的引用强度依次递减。

强引用

垃圾回收器是绝对不会回收这些存在强引用的对象,例如:A a = new A();当内存不足时,直接抛出OutOfMemory异常,而不会去做垃圾回收(或者手动调用gc)
image.png

软引用

描述一些有用但是非必须的对象。若内存将要溢出则对这些对象列入回收范围后进行二次回收。若这次回收还不能解决内存不足的问题时,则会抛出内存移除异常。
用“SoftReference”软引用类型的对象给包裹起来了,正常情况下不会回收软引用对象。
image.png

弱引用

这种对象只能生存到下一次垃圾回收发生之前。当垃圾回收开始时,无论当前内存是否足够,都会回收掉弱引用关联的对象
image.png

虚引用

虚引用在任何情况下都能被回收掉,它的作用仅仅用于跟踪对象垃圾回收的活动。

回收对象确定⭐

经历过可达性分析一番操作后,基本上要回收的对象已经确定了(此时并没有开始回收),这时要对这些对象做一些筛选,条件是对象是否有必要执行finalize()方法。
1.没有必要执行时直接被回收走
2.有必要执行时,会将这个对象放入一个叫F-Queue的队列中,并在稍后由一个虚拟机自动建立的、低优先级的Finalizer线程去执行它。
每个对象只能通过重写finalize方法拯救一次,在第二次标记的时候就会将它移除这个F-Queue队列
image.png