zygote启动的时候先创建一个active堆,等第一次fork子进程的时候再创建zygote堆
active堆创建
dvmGcStartup -> dvmHeapStartup->dvmHeapSourceStartup->
GcHeap* dvmHeapSourceStartup(size_t startSize, size_t maximumSize,
size_t growthLimit)
{
GcHeap *gcHeap;
HeapSource *hs;
mspace msp;
size_t length;
void *base;
......
/*
* Allocate a contiguous region of virtual memory to subdivided
* among the heaps managed by the garbage collector.
*/
length = ALIGN_UP_TO_PAGE_SIZE(maximumSize);
base = dvmAllocRegion(length, PROT_NONE, gDvm.zygote ? "dalvik-zygote" : "dalvik-heap");
......
/* Create an unlocked dlmalloc mspace to use as
* a heap source.
*/
msp = createMspace(base, kInitialMorecoreStart, startSize);
......
gcHeap = (GcHeap *)calloc(1, sizeof(*gcHeap));
......
hs = (HeapSource *)calloc(1, sizeof(*hs));
......
hs->targetUtilization = gDvm.heapTargetUtilization * HEAP_UTILIZATION_MAX;
hs->minFree = gDvm.heapMinFree;
hs->maxFree = gDvm.heapMaxFree;
hs->startSize = startSize;
hs->maximumSize = maximumSize;
hs->growthLimit = growthLimit;
......
hs->numHeaps = 0;
......
hs->heapBase = (char *)base;
hs->heapLength = length;
......
if (!addInitialHeap(hs, msp, growthLimit)) {
...... 创建一个Active堆。
}
if (!dvmHeapBitmapInit(&hs->liveBits, base, length, "dalvik-bitmap-1")) {
...... 创建和初始化一个Live Bitmap
}
if (!dvmHeapBitmapInit(&hs->markBits, base, length, "dalvik-bitmap-2")) {
...... 创建和初始化一个Mark Bitmap,
}
if (!allocMarkStack(&gcHeap->markContext.stack, hs->maximumSize)) {
...... 创建和初始化一个Mark Stack
}
gcHeap->markContext.bitmap = &hs->markBits;
gcHeap->heapSource = hs;
gHs = hs;
return gcHeap;
......
}
函数dvmHeapSourceStartup的执行过程如下所示:
-
将参数maximum指定的最大堆大小对齐到内存页边界,得到结果为length,并且调用函数dvmAllocRegion分配一块大小等于length的匿名共享内存块,起始地址为base。这块匿名共享内存即作为Dalvik虚拟机的Java堆。
-
调用函数createMspace将前面得到的匿名共享内存块封装为一个mspace,以便后面可以通过C库得供的mspace_malloc和mspace_bulk_free等函数来管理Java堆。这个mspace的起始大小为Java堆的起始大小,这意味着一开始在该mspace上能够分配的内存不能超过Java堆的起始大小。不过后面我们动态地调整这个mspace的大小,使得它可以使用更多的内存,但是不能超过Java堆的最大值。
3, 分配一个GcHeap结构体gcHeap和一个HeapSource结构体hs,用来维护Java堆的信息,包括Java堆的目标利用率、最小空闲值、最大空闲值、起始大小、最大值、增长上限值、堆个数、起始地址和大小等信信息。 -
调用函数addInitialHeap在前面得到的匿名共享内存上创建一个Active堆。这个Active堆的最大值被设置为Java堆的起始大小。
-
调用函数dvmHeapBitmapInit创建和初始化一个Live Bitmap和一个Mark Bitmap,它们在GC时会用得到。
-
调用函数allockMarkStack创建和初始化一个Mark Stack,它在GC时也会用到。
-
将前面创建和初始化好的Mark Bitmap和HeapSource结构体hs保存在前面创建的GcHeap结构体gcHeap中,并且将该GcHeap结构体gcHeap返回给调用者。同时,HeapSource结构体hs也会保存在全局变量gHs中
zygote堆创建
forkAndSpecializeCommon -> dvmHeapSourceStartupBeforeFork
bool dvmHeapSourceStartupBeforeFork()
{
HeapSource *hs = gHs; // use a local to avoid the implicit "volatile"
HS_BOILERPLATE();
assert(gDvm.zygote);
if (!gDvm.newZygoteHeapAllocated) {
/* Ensure heaps are trimmed to minimize footprint pre-fork.
*/
trimHeaps(); 此处清理收缩堆空间
/* Create a new heap for post-fork zygote allocations. We only
* try once, even if it fails.
*/
ALOGV("Splitting out new zygote heap");
gDvm.newZygoteHeapAllocated = true;
return addNewHeap(hs); 此处增加zygote堆
}
return true;
}