android每一个应用都有一个独立的进程,每个进程都是实例化了dalvik虚拟机实例的linux进程。Dalvik 主要管理的内存有 Java heap 和 native heap 两大块。Android系统对dalvik的vm heapsize作了硬性限制,当java进程申请的java空间超过阈值时,就会抛出OOM异常(这个阈值可以是48M、24M、16M等,视机型而定),而native heap大小则是不受次限制的。
当我们需要显示大的bitmap对象或者较多的bitmap的时候,如果使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置图片,则容易出现OOM,这个是因为bitpmap分配内存受限于java heap大小(一张在1024*1024图片,假设照片是用ARGB_8888格式,那么需要占用4M的内存存储像素点信息, bitmap分辨率越高,所占用的内存就越大,这个是以2为指数级增长的。)。此处引出一个问题:bitmap对象是分配在native heap还是java heap上的呢?后续会在单独一篇文章中讲解(Bitmap分配在java heap还是native heap)
在android 2.3和以前的版本,bitmap对象的像素数据都是分配在native heap中的,所以我们在调试过程中这部分内存是在java heap中看不到的,不过在android 3.0之后,bitmap对象就直接分配在java heap上了,这样便于调试和管理。因此在3.0之后我们可以复用bitmap的内存,而不必回收它,不过新的bitmap对象要大小和原来的一样,到了android 4.4之后,就只要高宽不超过原来的就行了。Bitmap是分配在dalvik heap上的,只有这样才能解释bitmap容易导致OOM。
refer to 参考链接
问题描述
该问题通常是在调用getWidth() 方法时,对应的Bitmap有时候出现为null,导致getWidth()方法出现空指针。
可能的原因
建议的调试方法:
通过引入if(unscaledBitmap == null)
的判断,进行断点调试。
public class BitmapScalingHelper
{
public static Bitmap decodeResource(Resources res, int resId, int dstWidth, int dstHeight)
{
Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
options.inJustDecodeBounds = false;
options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,
dstHeight);
options = new Options();
//May use null here as well. The funciton may interpret the pre-used options variable in ways hard to tell.
Bitmap unscaledBitmap = BitmapFactory.decodeResource(res, resId, options);
if(unscaledBitmap == null)
{
Log.e("ERR","Failed to decode resource - " + resId + " " + res.toString());
return null;
}
return unscaledBitmap;
}
}
可以尝试的解决办法:
SoftReference softRef = new SoftReference(BitmapFactory.decodeStream( input, null, options));
byte[] myArray = new byte[54];
myArray = null;
yourArray = myArray;
yourArray = null;
while true; do dumpsys meminfo 23637 | grep "TOTAL SWAP PSS:"; sleep 2; done,
while true; do dumpsys -t 600 meminfo --unreachable 7898 | grep "unreachable allocations" ; sleep 1; done
前者监控的是实际占用的内存,后者unreachable allocations监控的是(需要java的垃圾管理器要去释放的内存)
Android系统查看某个进程的线程
linux下top命令参数解释
垃圾回收机制与调用System.gc()区别
JNIEXPORT jint JNICALL Java_org_apache_tvm_LibInfo_tvmArrayCopyFromJArray(
JNIEnv *env, jobject obj, jbyteArray jarr, jlong jfrom, jlong jto) {
jbyte *data = env->GetByteArrayElements(jarr, NULL);
DLTensor *from = reinterpret_cast<DLTensor*>(jfrom);
//from->data = static_cast(data);
memcpy(from->data, static_cast<void *>(data), 150528);
int ret = TVMArrayCopyFromTo(static_cast<TVMArrayHandle>(from),
reinterpret_cast<TVMArrayHandle>(jto), NULL);
free(from->data);
from->data = NULL;
env->ReleaseByteArrayElements(jarr, data, 0);
ret
pthread_create failed: couldn’t allocate 1069056-bytes mapped space: Out of memory
Android 启动线程OOM
Android Framework中的线程Thread及它的threadLoop方法
JNI的原理及内存详解