当前位置: 代码迷 >> Android >> Android中的JVM怎么追蹤Bitmap buffer的大小
  详细解决方案

Android中的JVM怎么追蹤Bitmap buffer的大小

热度:52   发布时间:2016-05-01 20:49:18.0
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., JVM紀錄Bitmap的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自己管理。

  相关解决方案