深入理解Bitmap(二)

7 阅读1分钟

Bitmap 内存分布

android 9.0 Bitmap.cpp

static sk_sp<Bitmap> allocateHeapBitmap(size_t size, const SkImageInfo& info, size_t rowBytes) {
    void* addr = calloc(size, 1);
    if (!addr) {
        return nullptr;
    }
    return sk_sp<Bitmap>(new Bitmap(addr, size, info, rowBytes));
}

android 7.1.1 Graphics.cpp

android::Bitmap* GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
                                             SkColorTable* ctable) {
    const SkImageInfo& info = bitmap->info();
    if (info.colorType() == kUnknown_SkColorType) {
        doThrowIAE(env, "unknown bitmap configuration");
        return NULL;
    }


    size_t size;
    // 计算bitmap 需要占用的内存
    if (!computeAllocationSize(*bitmap, &size)) {
        return NULL;
    }

   
    // 通过jni 像java虚拟机申请一块内存
    jbyteArray arrayObj = (jbyteArray) env->CallObjectMethod(gVMRuntime,
                                                             gVMRuntime_newNonMovableArray,
                                                             gByte_class, size);
    if (env->ExceptionCheck() != 0) {
        return NULL;
    }
    SkASSERT(arrayObj);
    jbyte* addr = (jbyte*) env->CallLongMethod(gVMRuntime, gVMRuntime_addressOf, arrayObj);
    if (env->ExceptionCheck() != 0) {
        return NULL;
    }
    SkASSERT(addr);
    android::Bitmap* wrapper = new android::Bitmap(env, arrayObj, (void*) addr,
            info, rowBytes, ctable);
    // 实际的native 信息给 wrapper            
    wrapper->getSkBitmap(bitmap);
    // since we're already allocated, we lockPixels right away
    // HeapAllocator behaves this way too
    bitmap->lockPixels();

    return wrapper;
}

结论 :

Android < 8.0 之前 Bitmap 内存在java 堆内存中 ,内存申请首先Java堆内存大小限制 Android >= 8.0 Bitmap 内存在 Native内存中 ,内存不受限制,受系统内存大小

查看java 堆内存大小和Native 对内存

Java堆内存

private fun printMemoryInfo(){
        Runtime.getRuntime().also {
            Log.e("应用可以分配最大内存限制","${it.maxMemory().toM()}")
            Log.e("应用当前分配内存 ","${it.totalMemory().toM()}")
            Log.e("应用剩余内存 ","${it.freeMemory().toM()}")
            Log.e("应用已用内存 ","${it.totalMemory().toM().minus(it.freeMemory().toM())}")
        }
    }

Native 堆内存

   private fun printNativeMemoryInfo(){
        // Native 已经使用了多少
        "${Debug.getNativeHeapAllocatedSize().toM()}".logE("Native 已使用")
        // Native 还剩余多少
        "${Debug.getNativeHeapFreeSize().toM()}".logE("Native 剩余内存")
        // Native 堆本身内存大小
        "${Debug.getNativeHeapSize().toM()}".logE("Native 总内存大小")
    }