




下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、android bitmap内存限制 oom out of memory在编写 android程序的时候,我们总是难免会碰到oom 的错误,那么这个错误究竟是怎么来的呢?我们先来看一下这段异常信息:08-14 05:15:04.764: error/dalvikvm-heap(264): 3528000-byte external allocation too large for this process. 08-14 05:15:04.764: error/(264): vm wont let us allocate 3528000 bytes 08-14 05:15:04.764: deb
2、ug/skia(264): - decoder-decode returned false 08-14 05:15:04.774: debug/androidruntime(264): shutting down vm 08-14 05:15:04.774: warn/dalvikvm(264): threadid=3: thread exiting with uncaught exception (group=0 x4001b188) 08-14 05:15:04.774: error/androidruntime(264): uncaught handler: thread main ex
3、iting due to uncaught exception 08-14 05:15:04.794: error/androidruntime(264): java.lang.outofmemoryerror: bitmap size exceeds vm budget 08-14 05:15:04.794: error/androidruntime(264): at android.graphics.bitmapfactory.nativedecodeasset(native method) 08-14 05:15:04.794: error/androidruntime(264): at
4、 android.graphics.bitmapfactory.decodestream(bitmapfactory.java:447) 08-14 05:15:04.794: error/androidruntime(264): at android.graphics.bitmapfactory.decoderesourcestream(bitmapfactory.java:323) 08-14 05:15:04.794: error/androidruntime(264): at android.graphics.bitmapfactory.decoderesource(bitmapfac
5、tory.java:346) 08-14 05:15:04.794: error/androidruntime(264): at android.graphics.bitmapfactory.decoderesource(bitmapfactory.java:372) 08-14 05:15:04.794: error/androidruntime(264): at com.xixun.test.hellolistview.oncreate(hellolistview.java:33) 08-14 05:15:04.794: error/androidruntime(264): at andr
6、oid.app.instrumentation.callactivityoncreate(instrumentation.java:1047) 08-14 05:15:04.794: error/androidruntime(264): at android.app.activitythread.performlaunchactivity(activitythread.java:2459) 08-14 05:15:04.794: error/androidruntime(264): at android.app.activitythread.handlelaunchactivity(activ
7、itythread.java:2512) 08-14 05:15:04.794: error/androidruntime(264): at android.app.activitythread.access$2200(activitythread.java:119) 08-14 05:15:04.794: error/androidruntime(264): at android.app.activitythread$h.handlemessage(activitythread.java:1863) 08-14 05:15:04.794: error/androidruntime(264):
8、 at android.os.handler.dispatchmessage(handler.java:99) 08-14 05:15:04.794: error/androidruntime(264): at android.os.looper.loop(looper.java:123) 08-14 05:15:04.794: error/androidruntime(264): at android.app.activitythread.main(activitythread.java:4363) 08-14 05:15:04.794: error/androidruntime(264):
9、 at java.lang.reflect.method.invokenative(native method) 08-14 05:15:04.794: error/androidruntime(264): at java.lang.reflect.method.invoke(method.java:521) 08-14 05:15:04.794: error/androidruntime(264): at ernal.os.zygoteinit$methodandargscaller.run(zygoteinit.java:860) 08-14 05:15:04
10、.794: error/androidruntime(264): at ernal.os.zygoteinit.main(zygoteinit.java:618) 08-14 05:15:04.794: error/androidruntime(264): at dalvik.system.nativestart.main(native method) 从上面这段异常信息中,我们看到了一个oom(outofmemory)错误,我称其为(omg 错误 )。出现这个错误的原因是什么呢?为什么解码图像会出现这样的问题呢?关于这个问题,我纠结了一段时间,在网上查询了很多资
11、料,甚至查看了android issues,确实看到了相关的问题例如issue 3405,issue 8488,尤其 issue 8488下面一楼的回复,让我觉得很雷人啊:comment 1 by , may 23, 2010 your app needs to use less memory. 当然我们承认不好的程序总是程序员自己错误的写法导致的,不过我们倒是非常想知道如何来规避这个问题,那么接下来就是解答这个问题的关键。我们从上面的异常堆栈信息中,可以看出是在bitmapfactory.nativedecodeasset(),对应该方法的native方法是在bitmapfactory.cp
12、p中的dodecode()方法,在该方法中申请javapixelallocator对象时,会调用到graphics.cpp中的setjavapixelref()方法,在setjavapixelref()中会对解码需要申请的内存空间进行一个判断,代码如下:bool r = env-callbooleanmethod(gvmruntime_singleton, gvmruntime_trackexternalallocationmethodid, jsize); 而 jni 方法 id - gvmruntime_trackexternalallocationmethodid对应的方法实际上是dal
13、vik_system_vmruntime.c中的dalvik_dalvik_system_vmruntime_trackexternalallocation(),而在该方法中又会调用大heapsource.c中的dvmtrackexternalallocation()方 法,继 而调用到externalallocpossible()方法,在该方法中这句代码是最关键的heap = hs2heap(hs); currentheapsize = mspace_max_allowed_footprint(heap-msp); if (currentheapsize + hs-externalbytes
14、allocated + n absolutemaxsize) return true; 这 段 代 码 的 意 思 应 该 就 是 当 前 堆 已 使 用 的 大 小 ( 由currentheapsize和hs-externalbytesallocated构成 )加上我们需要再次分配的内存大小不能超过堆的最大内存值。那么一个堆的最大内存值究竟是多大呢。通过下面这张图,我们也许可以看到一些线索( 自己画的,比较粗糙) 最终的决定权其实是在init.c中,因为android在启动系统的时候会去优先执行这个里面的函数,通过调用dvmstartup()方法来初始化虚拟机,最终调用到会调用到heapso
15、urce.c中的dvmheapsourcestartup()方法,而在init.c中有这么两句代码:gdvm.heapsizestart = 2 * 1024 * 1024; / spec says 16mb; too big for us. gdvm.heapsizemax = 16 * 1024 * 1024; / spec says 75% physical mem 在另外一个地方也有类似的代码,那就是androidruntime.cpp中的 startvm()方法中:strcpy(heapsizeoptsbuf, -xmx); property_get(dalvik.vm.heapsi
16、ze, heapsizeoptsbuf+4, 16m); /logi(heap size: %s, heapsizeoptsbuf); opt.optionstring = heapsizeoptsbuf; 同样也是默认值为16m ,虽然目前我看到了两个可以启动vm 的方法, 具体 android何时会调用这两个初始化vm 的方法,还不是很清楚。不过可以肯定的一点就是,如果启动dvm 时未指定参数,那么其初始化堆最大大小应该就是16m ,那么我们在网上查到了诸多关于解码图像超过 8m 就会出错的论断是如何得出来的呢?我们来看看heapsource.c中的这个方法的注释/* * external
17、 allocation tracking * * in some situations, memory outside of the heap is tied to the * lifetime of objects in the heap. since that memory is kept alive * by heap objects, it should provide memory pressure that can influence * gcs. */ static bool externalallocpossible(const heapsource *hs, size_t n
18、) const heap *heap; size_t currentheapsize; /* make sure that this allocation is even possible. * dont let the external size plus the actual heap size * go over the absolute max. this essentially treats * external allocations as part of the active heap. * * note that this will fail mysteriously if t
19、heres * a small softlimit but a large heap footprint. */ heap = hs2heap(hs);currentheapsize = mspace_max_allowed_footprint(heap-msp); if (currentheapsize + hs-externalbytesallocated + n absolutemaxsize) return true; hstrace(externalallocpossible(): footprint %zu + extalloc %zu + n %zu = max %zu (spa
20、ce for %zu)n, currentheapsize, hs-externalbytesallocated, n, heap-absolutemaxsize, heap-absolutemaxsize - (currentheapsize + hs-externalbytesallocated); return false; 标为红色的注释的意思应该是说,为了确保我们外部分配内存成功,我们应该保证当前已分配的内存加上当前需要分配的内存值,大小不能超过当前堆的最大内存值,而且内存管理上将外部内存完全当成了当前堆的一部分。也许我们可以这样理解,bitmap对象通过栈上的引用来指向堆上的 bi
21、tmap对象,而 bitmap对象又对应了一个使用了外部存储的native图像,实际上使用的是 byte来存储的内存空间,如下图:我想到现在大家应该已经对于bitmap内存大小限制有了一个比较清楚的认识了。至于前几天从android123上 看 到 “android的btimap处 理 大 图 片 解 决 方 法 ” 一 文 中 提 到 的 使 用bitmapfactory.options来设置 intempstorage大小, 我当时看完之后就尝试了一下,这个设置并不能解决问题,而且很有可能会给你带来不必要的问题。从 bitmapfactory.cpp中的代码来看,如果option不为 null的话,那么会优先处
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 罐头食品标准与法规知识考核试卷
- 陈寿的‘职场生存手册’:《三国志》中的职场智慧解析
- 2025年签订租赁合同注意事项
- 2025建筑装修工程合同模板
- 2025移动房屋建设安装合同
- 隧道施工方法及其基本作业
- 苏教版六年级上册数学期末总复习教案2篇
- 二零二五版护士聘用合同
- 小水电站转让协议书
- 建筑物清洁合同书
- 团播签经纪合同和合作协议
- 车辆采购合同模板.(2025版)
- 浙江省杭州市萧山区2025年中考一模数学模拟试题(含答案)
- 浙江省丽水市发展共同体2024-2025学年高二下学期4月期中联考地理试卷(PDF版含答案)
- 田园综合体可行性研究报告
- 职业技术学院2024级跨境电子商务专业人才培养方案
- 沈阳市东北大学非教师岗位招聘考试真题2024
- 湖北省武汉市2025届高中毕业生四月调研考试数学试卷(含答案)
- 2025年中考语文二轮复习:散文阅读 专题练习题(含答案)
- 2025年3月版安全环境职业健康法律法规标准文件清单
- 四川自贡历年中考语文现代文之议论文阅读10篇(截至2024年)
评论
0/150
提交评论