垃圾是指在运行程序中没有任何指针指向的对象,就是需要被回收的。
执行程序会不断地分配内存空间,如果不进行回收,内存迟早都会被消耗完。
除了释放没用的对象,垃圾回收也可以清除内存里的记录碎片。碎片整理将所占用的堆内存移到堆的一端,以便JVM将整理出来的内存分配给新的对象
在堆空间和元空间中,GC这条守护线程会对这些空间开展垃圾回收⼯作,那么GC如何判断这些空间的对象是否是垃圾,有两种算法引用计数法和可达性分析算法:
每个对象有个引用计数器属性,记录被引用的情况。对象被引⽤,则计数器+1,如果计数器是0,那么对象将被判定为是垃圾,于是被回收。
这种算法,实现简单,判定效率高。但缺点是需要需要单独的字段存储计数器,每次赋值都需要更新计数器,增加了空间和时间的开销。缺最严重的是无法解决循环依赖问题。因此JVM⽬前的主流⼚商Hotspot没有使⽤这种算法。
注:什么是循环依赖问题?
如下图所示,p引用了A,对象A间接引用了C,C又引用了A。方法执行完p不再需要引用A,但A和C的引用没有消失,引用计数器还都是1,不会被回收。

该算法的基本思想就是:
通过一系列被称为「GC Roots」的根对象作为起始节点集,从这些节点开始,通过引用关系向下搜寻,搜寻走过的路径称为「引用链」,如果某个对象到GC
Roots没有任何引用链相连,就说明该对象不可达,即可以被回收。
哪些会被认定为GC Roots根呢?
synchronized锁住的对象也是绝对不能回收的,当前有线程持有对象锁呢,GC如果回收了对象,锁不就失效了。五种变量的位置如下:
静态变量会在方法区中存一个引用,市级指向堆内存,局部变量表也是如此。

总结
可达性分析就是JVM首先枚举根节点,找到一些为了保证程序能正常运行所必须要存活的对象,然后以这些对象为根,根据引用关系开始向下搜寻,存在直接或间接引用链的对象就存活,不存在引用链的对象就回收。
GC再扫描堆空间的某个节点时,会向上遍历,看看能不能遍历到gc roots根节点,如果不能,那么意味着这个对象是垃圾。
例如下图,对象4、5、6都没有和GC Root根节点相连,会被判定为垃圾回收。
