您的位置:首页 > 移动开发 > Android开发

Android 4.3 or later Bitmap 内存占用问题

2014-03-08 09:59 393 查看
最近在做到Skia 相关项目时,由于之前编译的so在Android 4.3 版本以后会出现Crash.经过查看源代码发现

SkBitmap->setConfig 参数列表已经发生了改变。包括GraphicsJNI.h 里面的很多函数参数列表也已经发生了改变。

于是就试着各种方法去解决,

解决思路:

1.  使用自己编译的skia.so

问题:GraphicsJNI 相关的也有改变,因此需要使用自己的Graphics.so. 感觉走远了。这样下去的apk将会很庞大,

于是尝试将Graphics.cpp 文件里createBitmap的源码copy出来 自己实现。(应该没问题)

最后自己再去看源码时,发现Android4.3 以后,在分配内存时已经没有进行内存控制了,而是Java heap 有多大就能分配多少,而且分配内存的函数也不一样了。

V??? or later 的Bitmap.cpp ->Bitmap_creator

//-----------------------Bitmap_creator------------------------------
GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);
//-------------------------------------------------------------------------
jbyteArray GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
SkColorTable* ctable) {
Sk64 size64 = bitmap->getSize64();
if (size64.isNeg() || !size64.is32()) {
jniThrowException(env, "java/lang/IllegalArgumentException",
"bitmap size exceeds 32bits");
return NULL;
}

size_t size = size64.get32();
jbyteArray arrayObj = env->NewByteArray(size);
if (arrayObj) {
// TODO: make this work without jniGetNonMovableArrayElements
jbyte* addr = jniGetNonMovableArrayElements(&env->functions, arrayObj);
if (addr) {
SkPixelRef* pr = new AndroidPixelRef(env, (void*) addr, size, arrayObj, ctable);
bitmap->setPixelRef(pr)->unref();
// since we're already allocated, we lockPixels right away
// HeapAllocator behaves this way too
bitmap->lockPixels();
}
}

return arrayObj;
}


<=V2.3

//-----------------------Bitmap_creator------------------------------
GraphicsJNI::setJavaPixelRef(env, &bitmap, NULL, true)
//-------------------------------------------------------------------------
bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
SkColorTable* ctable, bool reportSizeToVM) {
Sk64 size64 = bitmap->getSize64();
if (size64.isNeg() || !size64.is32()) {
doThrow(env, "java/lang/IllegalArgumentException",
"bitmap size exceeds 32bits");
return false;
}

size_t size = size64.get32();
jlong jsize = size;  // the VM wants longs for the size
if (reportSizeToVM) {
//    SkDebugf("-------------- inform VM we've allocated %d bytes\n", size);
bool r = env->CallBooleanMethod(gVMRuntime_singleton,
gVMRuntime_trackExternalAllocationMethodID,
jsize);
if (GraphicsJNI::hasException(env)) {
return false;
}
if (!r) {
LOGE("VM won't let us allocate %zd bytes\n", size);
doThrowOOME(env, "bitmap size exceeds VM budget");
return false;
}
}
// call the version of malloc that returns null on failure
void* addr = sk_malloc_flags(size, 0);
if (NULL == addr) {
if (reportSizeToVM) {
//        SkDebugf("-------------- inform VM we're releasing %d bytes which we couldn't allocate\n", size);
// we didn't actually allocate it, so inform the VM
env->CallVoidMethod(gVMRuntime_singleton,
gVMRuntime_trackExternalFreeMethodID,
jsize);
if (!GraphicsJNI::hasException(env)) {
doThrowOOME(env, "bitmap size too large for malloc");
}
}
return false;
}

SkPixelRef* pr = reportSizeToVM ?
new AndroidPixelRef(env, addr, size, ctable) :
new SkMallocPixelRef(addr, size, ctable);
bitmap->setPixelRef(pr)->unref();
// since we're already allocated, we lockPixels right away
// HeapAllocator behaves this way too
bitmap->lockPixels();
return true;
}


  

区别:SkMallocPixlRef(Alloc on Native) 和AndroidPixelRef(Alloc on Java Heap)

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: