系统中可以在prop中配置dalvik堆的有关设定。具体设定由如下三个属性来控制
数据在system/build.prop文件里存储
-dalvik.vm.heapstartsize
但是由于初始值较小,一些较大的应用需要扩张这个堆,从而引发gc和堆调整的策略,会应用反应更慢。
相反,这个值越大系统ram消耗越快,但是程序更流畅。
-dalvik.vm.heapgrowthlimit
dvm heap的大小是不会超过dalvik.vm.heapgrowthlimit的值(非正常情况下面会详细说明)。这个值控制那
些受控应用的极限堆大小,如果受控的应用dvm heap size超过该值,则将引发oom(out of memory)。
-dalvik.vm.heapsize
heap size。一旦dalvik heap size超过这个值,直接引发oom。
开始给一碗
一般人最多吃三碗
虎背熊腰的大汉最多能吃五碗
-
- static
void *tryMalloc(size_t size) - {
-
void *ptr; -
-
-
if (size >= gDvm.heapGrowthLimit) { -
LOGW("%zd byte allocation exceeds the %zd byte maximum heap size", -
size, gDvm.heapGrowthLimit); -
ptr = NULL; -
goto collect_soft_refs; -
} -
- //TODO:
figure out better heuristics - //
There will be a lot of churn if someone allocates a bunch of - //
big objects in a row, and we hit the frag case each time. - //
A full GC for each. - //
Maybe we grow the heap in bigger leaps - //
Maybe we skip the GC if the size is large and we did one recently - //
(number of allocations ago) (watch for thread effects) - //
DeflateTest allocs a bunch of ~128k buffers w/in 0-5 allocs of each other - //
(or, at least, there are only 0-5 objects swept each time) -
-
ptr = dvmHeapSourceAlloc(size); -
if (ptr != NULL) { -
return ptr; -
} -
-
-
if (gDvm.gcHeap->gcRunning) { -
-
dvmWaitForConcurrentGcTo Complete(); -
ptr = dvmHeapSourceAlloc(size); -
if (ptr != NULL) { -
return ptr; -
} -
} -
-
gcForMalloc(false); -
ptr = dvmHeapSourceAlloc(size); -
if (ptr != NULL) { -
return ptr; -
} -
-
-
ptr = dvmHeapSourceAllocAndGro w(size); -
if (ptr != NULL) { -
size_t newHeapSize; -
-
newHeapSize = dvmHeapSourceGetIdealFoo tprint(); - //TODO:
may want to grow a little bit more so that the amount of free - //
space is equal to the old free space + the utilization slop for - //
the new allocation. -
LOGI_HEAP("Grow heap (frag case) to " -
"%zu.zuMB for %zu-byte allocation", -
FRACTIONAL_MB(newHeapSize), size); -
return ptr; -
} -
-
- //TODO:
wait for the finalizers from the previous GC to finish - collect_soft_refs:
-
LOGI_HEAP("Forcing collection of SoftReferences for %zu-byte allocation", -
size); -
gcForMalloc(true); -
ptr = dvmHeapSourceAllocAndGro w(size); -
if (ptr != NULL) { -
return ptr; -
} - //TODO:
maybe wait for finalizers and try one last time -
-
LOGE_HEAP("Out of memory on a %zd-byte allocation.", size); - //TODO:
tell the HeapSource to dump its state -
dvmDumpThread(dvmThreadSelf(), false); -
-
return NULL; - }
这里分为如下几个动作
1
2
3
4
5
6
如果设置了largeHeap,具体流程从解析apk开始,源码位于PackagePaser.java中,其中parseApplication函数负责解析apk。其中有一个小段代码如下:
- if
(sa.getBoolean( -
com.android.internal.R.styleable.AndroidManifestApplicati on_largeHeap, -
false)) { -
ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP; -
}
如果解析到apk中设置了largeHeap,则在applicationinfo中添加FLAG_LARGE_HEAP标签。之后会在ActivityThead.java中的handleBindApplication处理,这个函数非常重要,底层process fork好之后,会由这个函数把上层应用绑定过去。并且调用上层应用的入口点。其中处理largeHeap的代码如下:
- if
((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) { -
dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); -
}
这里经过jni调用,最终回来到heapsource.cpp中的dvmClearGrowthLimit函数中:
-
- void
dvmClearGrowthLimit() - {
-
HS_BOILERPLATE(); -
dvmLockHeap(); -
dvmWaitForConcurrentGcTo Complete(); -
gHs->growthLimit = gHs->maximumSize; -
size_t overhead = oldHeapOverhead(gHs, false); -
gHs->heaps[0].maximumSize = gHs->maximumSize - overhead; -
gHs->heaps[0].limit = gHs->heaps[0].base + gHs->heaps[0].maximumSize; -
dvmUnlockHeap(); - }