- 通常来讲,全部指向对象的引用都已失效,不可能再有程序能调用到这个对象,那么这个对象就成了垃圾,应该被回收。
- 根据这个思路,很容易就能想到用《引用计数》的办法来肯定一个对象是不是垃圾。即每当多一个引用指向对象时,引用计数加一,每当少一个引用指向对象时,引用计数减一,引用计数减到零,对象就能够被回收了。
- 然而引用计数有一个致命问题很差解决,就是循环引用的问题。好比说一个循环链表,他们循环引用者,引用计数永远不会为零,可是实际上程序已经不能访问他们了,他们应该被回收。(若是还没明白循环引用,第五步以后有代码说明)
- 因此Java其实是使用基于GC Roots的可达性分析,什么是GC Roots?全部类的静态变量,每一个线程调用栈上的本地变量(实际上咱们编程时也是要从这些地方开始访问数据),全部这些对象,以及被这些对象所指向的对象,都是活的对象。活的对象所指向的对象也是活的对象。GC经过有向图的进行可达性分析,不可达的对象就被视为是垃圾对象。
- 因此只要在GC的时刻,让程序暂停运行,而后从GC Roots开始分析,最后没有被标记为活对象的对象就是垃圾了。
*代码事例解释什么是循环引用:对象

如上图所示,假设咱们有两个类分别是A和B,A类中有一个字段是B类的类型,B类中有一个字段是A类类型,如今分别new一个A类对象和new一个B类对象,此时引用a指向刚new出来的A类对象,引用b指向刚new出来的B类对象,而后将两个类中的字段互相引用一下,这样即便下面进行a = null和b = null,可是A类对象仍然被B类对象中的字段引用着,尽管如今A类和B类独享都已经访问不到了,可是引用计数却都不为0.blog
三.Java中有哪几种引用生命周期
- 强引用(StrongReference):强引用就是咱们平时使用的引用,是使用最广泛的引用。若是一个对象具备强引用,那垃圾回收器毫不会回收它(结合上面,一个对象有强引用,那么这个对象必定可达,也就是说明这个对象是活的)。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具备强引用的对象来解决内存不足的问题。(简记:永不回收)
- 软引用(SoftReference):若是一个对象只具备软引用,则内存空间足够,垃圾回收器就不会回收它;若是内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就能够被程序使用。因此,软引用可用来实现内存敏感的高速缓存。(简记:内存不足再回收)
- 弱引用(WeakReference):弱引用与软引用的区别在于:弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程当中,一旦发现了只具备弱引用的对象,无论当前内存空间足够与否,都会回收它的内存。不过,因为垃圾回收器是一个优先级很低的线程,所以不必定会很快发现那些只具备弱引用的对象。(简记:遇到就回收)
- 虚引用(PhantomReference):“虚引用”顾名思义,就是形同虚设,与其余几种引用都不一样,虚引用并不会决定对象的生命周期。若是一个对象仅持有虚引用,那么它就和没有任何引用同样,在任什么时候候均可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,若是发现它还有虚引用,就会在回收对象的内存以前,把这个虚引用加入到与之关联的引用队列中。(简记:形同虚设)