一、垃圾回收定义
垃圾回收是指如果一个对象,没有任何引用与之关联。则说明这个对象基本不大可能在其他的地方被用到,可能会成为垃圾对象。而这个对象所占用的内存空间,可以被清理,给新对象使用。
二、垃圾对象判定的算法
1.引用计数法
如果对象的引用计数为0,则认为这个对象不会被引用。可以作为回收对象。不失一般性,如果两个对象相互引用,则引用计数不会为0,这两个对象永远不会被回收。
MyObject object1 =
new
MyObject();
MyObject object2 =
new
MyObject();
object1.object = object2;
object2.object = object1;
object1 =
null
;
object2 =
null
;
2.可达性分析法
大致思路是,如果在跟节点和某个对象之前没有可达路径,我们就认为这个对象是不可达的,可以作为垃圾回收对象。判定一个对象为垃圾对象,需要经过两次标记,如果两次标记,都没逃脱被标记的对象,才认为对象是垃圾对象,可以垃圾回收。
三、垃圾收集算法
1.标记-清除算法(Mark-Sweep)
标记-清除算法分两个阶段:先标记垃圾对象,然后执行清除操作。这种做法,容易产生内存碎片。可能会造成对大的对象分配内存空间时,无法找到足够的空间,导致提前出发垃圾收集。
2.复制算法(Copy)
复制算法的思想是:将内存区域划分为大小相等的两块,然后等其中一块内存使用完,将存活对象全部复制到另一块,然后将这块全部清理掉。这种做法可以避免内存碎片。但是性价比不高,实际使用的内存为内存的一半。如果存活对象比较多,效率低下。
3.标记-整理(Mark-Compact)算法
为了解决复制算法的缺陷,当内存使用完后,将存活对象往一边移动,清理掉边界以外的空间。
4.分代收集算法(Generational Collection)
分代收集算法是目前大多数JVM使用的垃圾回收机制。核心思想是根据对象的生命周期,将内存划分为若干个区域。(新生代和老年代)。新生代区的对象存活时间短,每次垃圾回收时都有大量的对象被回收。老年代区的对象存活时间长,每次垃圾回收时只有少部分对象被回收,部分对象从新生代区转移到老年代区。
新生代收集算法一般采用Copying算法,新生代每次垃圾回收都要清理大部分对象,只有很少一部分需要执行复制操作。将新生代区划分为一个Eden区和两个Survivor区。每次使用Eden和其中的一块Survivor区,在垃圾回收的时候,将存活的对象复制到另外一个Survivor区。然后清理掉Eden和Survivor区。
老年代收集算法一般采用标记-整理(mark-Compact)算法,因为老年代区中清理的对象比较少。
在堆区外,还有一个区域叫永久代。用来存储class类,常量,方法描述等。
四、垃圾收集器
垃圾收集算法是内存回收的理论基础,垃圾收集器时内存回收的具体实现。
1.Serial/Serial Old
在垃圾回收的过程中,必须暂停所有用户进程。Serial是针对新生代,采用Copying算法。Serial Old 是针对老年代,采用Make-Compact算法。
2.ParNew
ParNew是Serial/Serial Old的多线程版本。
3.Parallel Scavenge
多线程收集器,不需要停顿其他进程。采用Copying达到一个可控的吞吐量。
4.Parallel Old
Parallel Old 是Parallel Scavenge的老年代版本,采用Make-compact算法。
5.CMS(current make sweep)
获取最短停顿时间为目的的收集器,采用mak-sweep算法
6.G1
面向服务端应用的收集器,充分利用多CPU,多核环境,能建立可预测的停顿模型。