垃圾收集算法

 
1. 标记 - 清除

 

 

在标记阶段,程序会检查每个对象是否为活动对象,如果是活动对象,则程序会在对象头部打上标记。
Object obj = new Object();
SoftReference<Object> sf = new SoftReference<Object>(obj);
obj = null; // 使对象只被软引用关联
Object obj = new Object();
WeakReference<Object> wf = new WeakReference<Object>(obj);
obj = null;
Object obj = new Object();
ReferenceQueue queue = new ReferenceQueue();
PhantomReference<Object> pf = new PhantomReference<Object>(obj, queue);
obj = null;在清除阶段,会进行对象回收并取消标志位,另外,还会判断回收后的分块与前一个空闲分块是否连
续,若连续,会合并这两个分块。回收对象就是把对象作为分块,连接到被称为 “空闲链表” 的单向链
表,之后进行分配时只需要遍历这个空闲链表,就可以找到分块。
在分配时,程序会搜索空闲链表寻找空间大于等于新对象大小 size 的块 block。如果它找到的块等于
size,会直接返回这个分块;如果找到的块大于 size,会将块分割成大小为 size 与 (block - size) 的两部
分,返回大小为 size 的分块,并把大小为 (block - size) 的块返回给空闲链表。
不足:
标记和清除过程效率都不高;
会产生大量不连续的内存碎片,导致无法给大对象分配内存。
 
2. 标记 - 整理

 

 

让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
优点:
不会产生内存碎片
不足:
需要移动大量对象,处理效率比较低。
3. 复制

 

 

将内存划分为大小相等的两块,每次只使用其中一块,当这一块内存用完了就将还存活的对象复制到另
一块上面,然后再把使用过的内存空间进行一次清理。有两块Survivor区是为了防止内存碎片化。
主要不足是只使用了内存的一半。
现在的商业虚拟机都采用这种收集算法回收新生代,但是并不是划分为大小相等的两块,而是一块较大
的 Eden 空间和两块较小的 Survivor 空间,每次使用 Eden 和其中一块 Survivor。在回收时,将 Eden
和 Survivor 中还存活着的对象全部复制到另一块 Survivor 上,最后清理 Eden 和使用过的那一块
Survivor。
HotSpot 虚拟机的 Eden 和 Survivor 大小比例默认为 8:1:1,保证了内存的利用率达到 90%。如果每次
回收有多于 10% 的对象存活,那么一块 Survivor 就不够用了,此时需要依赖于老年代进行空间分配担
保,也就是借用老年代的空间存储放不下的对象。
4. 分代收集
现在的商业虚拟机采用分代收集算法,它根据对象存活周期将内存划分为几块,不同块采用适当的收集
算法。
一般将堆分为新生代和老年代。
新生代使用:复制算法
老年代使用:标记 - 清除 或者 标记 - 整理 算法
posted @ 2020-07-21 15:21  miracleyy  阅读(32)  评论(0)    收藏  举报