要实现自己的垃圾回收算法,首先要实现一套自己的内存分配方法,把内存的管理权掌握在自己手里,而不是每次都调用系统函数,向操作系统要一小块内存,否则垃圾回收就无从谈起。思路主要是:
一开始申请一块大的内存,后面每次程序需要内存就从这个内存块中分配,不够了再想办法处理(垃圾回收、压缩、分配更大的内存等)。
上面申请的一块大的内存一般叫做堆(heap)。名字叫什么不要紧,反正就是内存的一部分,申请下来后都归自己管理了。
很多软件都用类似的方法来管理内存,借鉴市场经济的做法,从多次的少量”购买“变成一次”大量批发“,的确是一种进步。
1. 关键数据结构与基本操作
1.1 堆的结构以及基本操作
目前我们只需要知道堆(heap)的起始地址、堆中空闲内存的起始地址、堆的结束地址即可。
定义一个数据结构来表示堆(各字段含义如其名字所示):
typedef struct _Heap {
char *start_addr;
char *free_addr;
char *end_addr;
}Heap;
示意图如下:
创建一个堆可以用如下方法:
Heap* new_heap(uint size) {
Heap *heap = (Heap*)malloc(sizeof(Heap)+size);
heap->start_addr = (char*)heap + sizeof(Heap);
heap->free_addr = heap->start_addr;
heap->end_addr = heap->start_addr + size;
return heap;
}
够简单了吧,无须解释。
1.2 对象的结构以及基本操作
堆是用来动态分配内存给对象用的,所以我们还得需要知道对象的结构。参考“自制Java虚拟机”中对象的结构,当前为了测试方便,定义对象的结构如下(包含对象的一些头部信息以及对象的字段指针):
typedef struct _Object {
char flag;
ushort length;
char* fields;
}Object;
示意图如下:
关于对象,有如下基本操作:
// 1.获取整个对象的占用空间大小
#define OBJ_SIZE(obj) (sizeof(Object) + (obj->length<<2))