因为毕业设计做Dalvik内存管理方面的优化。
这些天仔细阅读了下线性分配器LinearAlloc的代码
线性分配器代码为于android_src/dalvik/vm/目录下的
只有两个文件LinearAlloc.h和LinearAlloc.c代码很少,约800多行而已
线性分配器的目的在于简单、快速地分配只写一次(write-once)的内存(即分配并完成初始化写入后一般不会再改变,保持只读性质)
它主要用来管理Dalvik中类加载时的内存,因为类加载后通常是只读属性,而不需要去改变
且在程序的整个运行周期都是有效的,同时它还有共享的特性,一个应用加载后其它进程可以共享使用这些已加载的类从而加快程序的启动和运行速度
另外,在Java中动态分配内存是由堆来管理的,需要一个垃圾收集器来管理垃圾,对于永久存在的内存区不需要垃圾收集器的扫描清除,
所以将这些永久存在的内存块放到线性分配器中管理能很好地减少堆混乱和垃圾扫描,加快系性能
好吧,进入正题:
线性内存分配器用shmem从系统中申请一块大小为5M的内存,然后用自己的接口来管理它,提供分配和释放内存的API
它的线性在于分配内存从低地址到高地址,先分配的在前,后分配的在后
每个Dalvik虚拟机实例有个全局的LinearAllocHdr结构体来描述当前虚拟机的线性分配器
gDvm.pBootLoaderAlloc
以下是它的唯一一个数据结构
/*
* Linear allocation state. We could tuck this into the start of the
* allocated region, but that would prevent us from sharing the rest of
* that first page.
线性分配状态,可以将它放到分配区域的前段,但是那会防碍共享它的第一页之外的页
*/
typedef struct LinearAllocHdr {
int curOffset; /* offset where next data goes *///下一次分配的地址
pthread_mutex_t lock; /* controls updates to this struct *///用来多线程同步的锁
char* mapAddr; /* start of mmap()ed region *///分配器管理的整块内存的起始地址
int mapLength; /* length of region *///整块内存长或大小
int firstOffset; /* for chasing through *///第一次分配的位置
/* 描述内存中这些页的读写权限 它指向一个位图,位图中的每位为16bit,用来存放对应页写的次数*/
short* writeRefCount; /* for ENFORCE_READ_ONLY */
} LinearAllocHdr;
/*
* 创建一个线性分配器
*/
LinearAllocHdr* dvmLinearAllocCreate(Object* classLoader);
/*
* 销毁线性分配器
*/
void dvmLinearAllocDestroy(Object* classLoader);
/*
* 从线性分配器中分配内存
*/
void* dvmLinearAlloc(Object* classLoader, size_t size);
/*
* 释放线性分配器中的内存,注意它不会增加可用的线性内存,只是用来协助其它程序调试用
*/
void dvmLinearFree(Object* classLoader, void* mem);
还有一些其它的API,如
//重新分配大小来存储原来的内容
void* dvmLinearRealloc(Object* classLoader, void* mem, size_t newSize);
//使这块区域只读
INLINE void dvmLinearReadOnly(Object* classLoader, void* mem)
//全可读写
INLINE void dvmLinearReadWrite(Object* classLoader, void* mem)
//同C中的strup,用来申请内存存放str中的内容,使用完后由用户负责调用释放
char* dvmLinearStrdup(Object* classLoader, const char* str);
//调试用,用来打印内存中的内容
void dvmLinearAllocDump(Object* classLoader);
//检查从[start,start+length)这个区域是否在线性分配的已分配区间中
bool dvmLinearAllocContains(const void* start, size_t length);