Android中的JVM如何追Bitmap buffer的大小
http://oxygenplan.blogspot.sg/2011/02/androidjvmbitmap-buffer.html
?
在Android面,app索取memory,此若process的memory使用量超上限,JVM出out of memory的exception,我可以在Heap.c面的dvmMalloc(size_t size, int flags)找到.
void* dvmMalloc(size_t size, int flags) {
...
ptr = tryMalloc(size);
...
if (ptr != NULL) {
...
} else {
...
?LOGE("Out of memory: Heap Size=%dKB, Allocated=%dKB,?Bitmap Size=%dKB, Limit=%dKB",
?? ? ? ? ? ?dvmHeapSourceGetValue(HS_ALLOWED_FOOTPRINT, NULL, 0)/1024,
?? ? ? ? ? ?dvmHeapSourceGetValue(HS_BYTES_ALLOCATED, NULL, 0)/1024,
?? ? ? ? ? ?dvmHeapSourceGetValue(HS_EXTERNAL_BYTES_ALLOCATED, NULL, 0)/1024,
?? ? ? ? ? ?gDvm.heapSizeMax / 1024);
...
}
...
}
但是本篇中,我只注於Bitmap面pixel buffer的使用量.source code中可,VM是控HS_EXTERNAL_BYTES_ALLOCATED的使用量,控管Bitmap size.
我一段的sample code, 看看HS_EXTERNAL_BYTES_ALLOCATED的memory使用量的化.
public class Foo {
?? ? public void monitorBitmap() {
?? ? ? ? ?Bitmap src =?Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
?? ? ? ? ?...
?? ? ? ? ?src.recycle();
?? ? }
}
在sample code的monitorBitmap()中只做了件事情:
1. new一Bitmap,
2. 回收它(recycle()).
首先,trace?create?Bitmap object 的程,
1. createBitmap(int width, int height, Config config); [Bitmap.java]
2. nativeCreate(int[] colors, int offset,??int stride, int width, int height,?int nativeConfig, boolean mutable);?[Bitmap.java]
---JNI------------------------------------------------------
3. Bitmap_creator(JNIEnv* env, jobject, jintArray jColors, int offset, int stride, int width, int height, SkBitmap::Config config, jboolean isMutable); [Bitmap.cpp]
4. GraphicsJNI::setJavaPixelRef(env, &bitmap, NULL, true); [Graphics.cpp]
5.1.?JNIEnv::CallBooleanMethod(gVMRuntime_singleton, gVMRuntime_trackExternalAllocationMethodID, jsize);?[Graphics.cpp]
5.2. void* addr = sk_malloc_flags(size, 0);?[Graphics.cpp]
5.3. SkPixelRef* pr = new AndroidPixelRef(env, addr, size, ctable, reportSizeToVM);?[Graphics.cpp]
5.4. bitmap->setPixelRef(pr)->unref();?[Graphics.cpp]
在步5.1., JVMBitmap的size,追它. 5.2.,5.3. malloc pixel buffer同放入SkPixelRef object中以方便控管. SkPixelRef承SkRefCnt,因此使用了reference count的技巧,可以有多少object考到它. 5.4. SkPixelRef放入SkBitmap, 同先前Bitmap object部所持有的SkPixelRef object unref().
最後,我看Bitmap object被recycle(),做了哪些理:
1. recycle(); [Bitmap.java]
2. nativeRecycle(int nativeBitmap);?[Bitmap.java]
---JNI------------------------------------------------------
3. Bitmap_recycle(JNIEnv* env, jobject, SkBitmap* bitmap); [Bitmap.cpp]
4. SkBitmap::setPixels(NULL, NULL); [SkBitmap.cpp]
5. SkBitmap::freePixels();?[SkBitmap.cpp]
6. AndroidPixelRef::unref(); [Graphics.cpp]
7. AndroidPixelRef::~AndroidPixelRef();?[Graphics.cpp]
8.?JNIEnv::CallVoidMethod(gVMRuntime_singleton, gVMRuntime_trackExternalFreeMethodID, jsize);?[Graphics.cpp]
在步8, JVM移除先前所的pixel buffer size的.
由上面的例中,我可以得知JVM是如何追Bitmap size的大小.
?
Dalvik:
进行数据统计,然后调用GC。其实还是全部靠Bitmap自己管理。