# 对象信息
对象信息分为对象头和域两部分,对象头持有对象的一些描述信息,比如mark标记(用于垃圾回收时进行标记),size(用于记录对象占用内存大小)等;而域则是保存有毒性的属性信息;
# 标记-清除算法
标记-清除算法将垃圾回收分为标记和清除两个阶段。
标记阶段:此阶段会将堆中存活的对象打上标记。具体操作为以gc root为节点,通过深度遍历(广度遍历也可以,但是广度遍历会占用更多的内存空间)的方式遍历所有被gc root直接或者间接持有的对象,如果对象还未被标记,则进行标记。所以这个过程耗时与堆中的存活对象个数呈正相关。
清除阶段:此阶段会将堆中未进行标记的内存执行清除操作。在这个阶段,收集器会遍历整个堆内存,如果遇到的对象的mark标记为true,则会对该标记设置为未标记状态,这样能保证下一次垃圾回收过程能够对该对象进行标记;
如果遇到的对象未被标记,则说明此对象已经是垃圾对象,需要进行回收处理。此时可能会进行两种处理:
1 将被回收对象对应的内存链接到空闲列表中;
2 如果被回收的对象与空闲列表中的内存存在连续的情况,则会将这些内存进行合并,进而得到一块更大的内存;
## 内存分配
从空闲链表中查找得到一块大小合适的内存的内存块的过程叫做内存分配,查找合适内存块的方式主要有三种:
1 First-fit:找到第一块足够大小的内存块就返回,这种方式是最快的;
2 Best-fit:遍历空闲链表,找到最接近需要的大小的内存空间,这种方式内存的利用率最高;
3 Worst-fit:找到空闲链表中最大的内存块,并从该内存块中切出需要的大小,这种方式会产生大量的小内存块,导致内存浪费;
# 优缺点
优点:简单易实现;由于整个过程不移动对象,与保守式GC算法兼容(保守式GC算法不需要移动对象);
缺点:内存碎片化;回收效率不高(两次扫描内存);内存分配效率不高(遍历空闲列表);与写时复制技术不兼容(因为写时复制会涉及到内存地址的移动,而对对象进行标记时会涉及mark标记的修改进而触发对象复制,但是整个对象复制代价过大);
# 改进措施
1 多空闲链表:将空闲内存块按照大小分组,以此减少查找合适内存块的时间;
2 BiBOP法:将内存空间分块后,将相同大小的对象聚集分配,以此降低碎片化问题,但是同样可能降低内存的利用率;
3 位图标记法:将对象头中的mark标记统一存储于位图表格,以此一方面兼容写时复制技术(位图表格内存占用小,进行写时复制操作代价低),另一方面加快标志位的恢复速度(操作位图表格比遍历堆内所有存活对象的标志位耗时更低);