垃圾收集器回收的是什么?当然是"垃圾"。那什么是"垃圾"呢?在生活中当一个东西对我们来说已经没有使用价值,无法利用时,便会作为"垃圾"被我们丢弃掉。同理在JVM中当一个对象不会再被使用时,就成为垃圾回收器回收的对象—“垃圾”。为什么要回收"垃圾"呢?生活中,我们的房间空间是一定的,如果不清理"垃圾",会使得我们可利用的空间会越来越小,JVM中如果没有垃圾回收,也就是所占据的空间将不可回收,这就会造成了内存泄露。
读过上文的应该知道,Java中几乎所有的对象实例都在Java堆中分配内存,方法区用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。所以垃圾收集器进行回收的区域是:堆和方法区中。
如何判断是否为"垃圾"
引用计数算法
引用计数算法是最古老的辨别方法。首先在对象中添加一个引用计数器,初始值为零,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;所以任何时刻当一个对象的计数器值为零时,代表此对象没有被任何地方引用,也就是垃圾收集器要回收的"垃圾"。
客观地说,引用计数算法虽然占用了一些额外的内存空间来进行计数,但它的原理简单,判定效率也很高,在大多数情况下它都是一个不错的算法。但是在Java 领域,至少主流的Java虚拟机里面都没有选用引用计数算法来管理内存,主要原因是,这个看似简单的算法有很多例外情况要考虑,必须要配合大量额外处理才能保证正确地工作,譬如单纯的引用计数就很难解决对象之间相互循环引用的问题。
所谓对象之间的相互引用问题:除了对象a和b相互引用着对方之外,这两个对象之间再无任何引用。但是它们因为互相引用对方,导致它们的引用计数器都不为0,于是引用计数器法无法通知GC回收器回收它们。如下图红色区域。
可达性分析算法
基本思路就是通过 一系列称为“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”,如果某个对象可以根据引用链到达GC Root,那么说明这个对象被引用中,反之,则证明此对象是不可能再被使用的。如下图所示。
在Jav