众所周知,Java是一门不用程序员手动管理内存的语言。全靠JVM自动管理内存,既然是自动管理,那必然有一个垃圾内存的回收机制或者回收算法。本文主要对几种常见的垃圾回收算法进行整理和归纳。
一、如何判断对象被引用?
主要有引用计数算法和可达性算法。引用计数算法比较简单,就是做个计算器,对象被引用就加一,取消引用就减一,计数是零就是没有人引用。缺点是面试最常问的循环引用问题。目前没有太好的解决方法。所以这种算法目前jvm'基本不用。可达性算法就是在root节点开始扫描,扫描到的就是有引用的,没扫描到的就是没有。缺点就是时间长,而且必须stop the world。是jvm目前在使用的算法。下面的回收算法会尽量减少这种缺点的影响。
二、垃圾回收算法
上面说到了怎么确定对象是否要被回收。可是确定了之后具体要怎么回收呢?
1、复制算法
2、标记清除算法
3、标记整理算法
4、分代回收算法
说是有4种,实际就是3种。因为分代回收算法其实就是上面三种算法的综合应用,也是目前jvm使用的算法。
首先,复制算法,就是把有用的对象复制下来,原来的全部删除,优点是速度最快,缺点就是占用内存空间比较多。
其次,标记清除,就是 把没用的对象直接删除,优点是速度第二快,也不会很很占用内存空间。缺点是会产生内存碎片。
再次,标记整理,由于标记清除会产生内存碎片,为了解决问题,对内存存活的对象进行整理。优点是不会占用很多内存,也不会产生内存碎片,缺点也很明显,就是慢。
最后,分代回收,分代回收只是上述三种算法的应用。下面介绍怎么应用的。
三种算法各有优缺点,适用不同的场合。于是jvm就将其内存对象分类。不同类型用适合的回收算法。
1、新生代
2、老年代
3、持久代
首先,新生代,新生代就是刚创建出来的对象,这些对象大部分朝生夕死,更新很快。选用速度最快的回收算法--复制算法。既然是复制算法,就需要额外的内存空间存放复制的对象。所以新生代的内存分为三个部分。这部分在此不详细介绍,不影响后续理解。
其次,老年代,老年代就是新生代创建的经过一段时间还存在的对象。这些对象在未来的某个时间会死亡,但是不会太频繁。使用的回收算法是标记清除或标记整理。(具体需要下文看垃圾回收器)
最后,持久代,持久代就是 对内存回收没有太大影响。也没有回收算法。