前言
首先,我们要讲的是JVM的垃圾回收机制,我默认准备阅读本篇的人都知道以下两点:
- JVM是做什么的
- Java堆是什么
因为我们即将要讲的就是发生在JVM的Java堆上的垃圾回收,为了突出核心,其他的一些与本篇不太相关的东西我就一笔略过了
众所周知,Java堆上保存着对象的实例,而Java堆的大小是有限的,所以我们只能把一些已经用完的,无法再使用的垃圾对象从内存中释放掉,就像JVM帮助我们手动在代码中添加一条类似于C++的free语句的行为
然而这些垃圾对象是怎么回收的,现在不知道没关系,我们马上就会讲到
怎么判断对象为垃圾对象
在了解具体的GC(垃圾回收)算法之前,我们先来了解一下JVM是怎么判断一个对象是垃圾对象的
顾名思义,垃圾对象,就是没有价值的对象,用更严谨的语句来说,就是没有被访问的对象,也就是说没有被其他对象引用,这就牵引出我们的第一个判断方案:引用计数法
引用计数法
这种算法的原理是,每有一个其他对象产生对A对象的引用,则A对象的引用计数值就+1,反之,每有一个对象对A对象的引用失效的时候,A对象的引用计数值就-1,当A对象的引用计数值为0的时候,其就被标明为垃圾对象
这种算法看起来很美好,了解C++的应该知道,C++的智能指针也有类似的引用计数,但是在这种看起来“简单”的方法,并不能用来判断一个对象为垃圾对象,我们来看以下场景:
在这个场景中,A对象有B对象的引用,B对象也有A对象的引用,所以这两个对象的引用计数值均不为0,但是,A、B两个对象明明就没有任何外部的对象引用,就像大海上两个紧挨着的孤岛,即使他们彼此依靠着,但仍然是孤岛,其他人过不去,而且由于引用计数不为0,也无法判断为垃圾对象,如果JVM中存在着大量的这样的垃圾对象,最终就会频繁抛出OOM异常,导致系统频繁崩溃
总而言之,如果有人问你为什么JVM不采用引用计数法来判断垃圾对象,只需要记住这一句话:引用计数法无法解决对象循环依赖的问题