JVM学习笔记二 - 垃圾收集 博客分类: JVM 垃圾收集
JVM的垃圾收集主要是对JAVA堆进行收集,JAVA堆分为新生代和老年代。
(1)、新生代区域:指存放新创建的对象或者未达到老年代要求的对象。
(2)、老年代区域:除新生代外的内存空间,就是老年代的内存空间,用于存放长久未被收集的对象。
1、对象是否需要收集?
如何判断一个对象是否需要收集?这个问题一般采用如下两种算法进行处理:
(1)、引用计数算法(Reference Counting):给对象添加一个引用计数器,每当有一个地方引用对象,计数器就加1;当引用失效时,计数器就减1;任何时刻计数器的值为0时,都认为对象已经可以回收了。这种方式的缺点是很难判断相互引用的对象。
(2)、根搜索算法(GC Roots Tracing):通过名为"GC Roots"的对象作为起点,当对象到GC Roots的路径不可到达时,则证明此对象是不可用的。JAVA采用这种算法。
JAVA中,可作为GC Roots的对象有:
- 虚拟机栈(栈帧中的本地变量表)中引用的对象。
- 方法区中的类静态属性引用的对象。
- 方法区中常量引用的对象。
- 本地方法栈中JNI引用的对象。
2、垃圾收集算法
(1)、标记-清除(Mark-Sweep)算法:最基础的垃圾收集算法,分为“标记”和“清除”两个阶段进行垃圾收
集:首先标记出所有需要回收的对象,标记完成后统一回收掉所有被标记的对象。
这种算法存在两个缺点:
1)、效率问题:标记和清除过程的效率都不高;
2)、空间问题:回收后会产生大量的空间碎片,影响大对象分配时的空间利用。
(2)、复制(Copying)算法:将内存空间分为大小相等的两块,每次只使用其中的一块内存,当这一块的内存用得差不多了,就把还存活着的对象复制到另一块内存中,然后把使用的内存空间全部清理掉。这样的好处是不需要考虑内存碎片空间的管理。缺点是需要损失一半的内存。
新生代采用这种算法,但是不是使用1:1的方式进行分配,因为新生代中的大部分对象在垃圾收集发生时将会被回收,因此它将内存区域划分为一个Eden区和两个Survivor区,Eden和Survivor的比例默认为8:1。
(3)、标记-整理算法(Mark-Compact):过程跟"标记-清除"算法一致,只是在最后不是一次清除所有存活的对象,而是将存活的对象移动到一端,然后将端边界外的内存进行清理。
(4)、分代收集算法(Generational Collection):根据对象的周期特点,采用特定的算法进行收集,一般是把Java堆分为新生代和老年代,在新生代中,采用”复制“算法;在老年代中,采用”标记-整理“或者”标记-清理“算法。
3、垃圾收集器
垃圾收集器是各种垃圾收集算法的具体实现。先看看JDK6中垃圾收集器的组成图: