分代收集算法
??无论是标记清除算法、复制算法还是标记整理算法,都无法对所有类型(长生命周期、短生命周期、大对象、小对象)的对象都进行垃圾回收。因此,针对不同的对象类型,JVM采用了不同的垃圾回收算法,该算法被称为分代收集算法。
??分代收集算法根据对象的不同类型将内存划分为不同的区域,JVM将堆划分为新生代和老年代。新生代主要存放新生成的对象,其特点是对象数量多但是生命周期短,在每次进行垃圾回收时都有大量的对象被回收;老年代主要存放大对象和生命周期长的对象,因此可回收的对象相对较少。因此,JVM根据不同的区域对象的特点选择了不同的垃圾回收算法。
??目前,大部分JVM在新生代都采用了复制算法,因为在新生代中每次进行垃圾回收时都有大量的对象被回收,需要复制的对象(存活的对象)较少,不存在大量的对象在内存中被来回复制的问题,因此采用复制算法能安全、高效地回收新生代大量的短生命周期的对象并释放内存。
??JVM将新生代进一步划分为一块较大的Eden区和两块较小的Survivor区,Survivor区又分为SurvivorFrom区和SurvivorTo区。JVM在运行过程中主要使用Eden区和SurvivorFrom区,进行垃圾回收时会将在Eden区和SurvivorFrom区中存活的对象复制到SurvivorTo区,然后清理Eden区和SurvivorFrom区的内存空间,如下图所示:
??老年代主要存放生命周期较长的对象和大对象,因而每次只有少量非存活的对象被回收,因而在老年代采用标记清除算法。
??在JVM中还有一个区域,即方法区的永久代,永久代用来存储Class类、常量、方法描述等。在永久代主要回收废弃的常量和无用的类。
??JVM内存中的对象主要被分配到新生代的Eden区和SurvivorFrom区,在少数情况下会被直接分配到老年代。在新生代的Eden区和SurvivorFrom区的内存空间不足时会触发一次GC,该过程被称为MinorGC。在MinorGC后,在Eden区和SurvivorFrom区中存活的对象被复制到SurvivorTo区,然后Eden区和SurvivorFrom区被清理。如果此时在SurvivorTo区无法找到连续的内存空间存储某个对象,则将这个对象直接存储到老年代。若Survivor区的对象进过一次GC后仍然存活,则其年龄加 1.在默认情况下,对像在年龄达到15时,将被转移到老年代。