# 原始算法
| Mark-Sweep | Mark-Compact | Copying | |
|---|---|---|---|
| 速度 | 中等 | 最慢 | 最快 |
| 空间开销 | 少(但会堆积碎片) | 少(不堆积碎片) | 通常需要活对象的2倍大小(不堆积碎片) |
| 移动对象 | 否 | 是 | 是 |
# 标记清除算法 Mark-Sweep
- 标记出哪些对象是存活对象
- 在内存中回收存活对象之外的垃圾对象
# 标记压缩算法 Mark-Compact
- 标记出哪些对象是存活对象
- 将所有存活对象压到内存一边,按顺序排放
- 清空余下空间
# 复制算法 Copying
- 准备两个内存区A、B
- 标记出哪些对象是存活对象
- 将A区存活对象整体移动到B区中,并且压缩排列
- 清空A区
- B区回收时,重复上面的操作
# 指针碰撞和空闲列表
假设java堆中内存是绝对规整的,所有用过的内存放一边,未使用过的放一边,中间有一个指针作为临界点,如果新创建了一个对象则是把指针往未分配的内存挪动与对象内存大小相同距离,这个称为指针碰撞。
如果Java堆中的内存分配不是规整的,虚拟机就会维护一个空闲列表,用来记录剩余的可用内存空间,每次为变量分配内存后,动态的区维护这个列表
# 改进算法
# 分代复制算法
- 将内存区划分成Eden区、s1区、s2区、Old区
- 新分配的对象在Eden区,垃圾回收时,把存活的对象放到s1区,清空Eden区
- 第二次再回收时,统计Eden区、s1区存活对象,放到s2区,清空Eden区和s1区
- 反复操作Eden、S1、S2区即可,Eden、S1、S2来回操作的过程称为Minor GC
- 如果有的对象始终不被回收,达到一定代数之后会转入到Old区,或者有的对象特别大,无法进入Eden区或者回收时无法进入S区,则直接进入Old区
- Old区满了,一般整体再回收一次,进行FullGC,FullGC=MinorGC+MajorGC
几乎现在的JVM都采用了分代模型,在分代的基础上再进行各种优化取舍