Bitmap 究竟占多大内存
2017-09-02
展开全部
最近在做一款塔防游戏,用的事surfaceview框架,由于图片过多,而且游戏过程中都需要这些图片,所以加载成bitmap后造成OOM(outofmemory)异常。下面是我一步一步找解决此问题的纪录,再此分享,希望对以后出现此问题的开发者有所帮助。第一:出现问题,我的测试手机是2。2android操作系统,不会出现oom问题,但是在老板的android4.2上却出现了问题,因为是oom,所以我首先想到的是手动改变手机的内存大小限制。网上有些帖子说可以通过函数设置应用的HEAPSIZE来解决这个问题,其实是不对的。VMRuntime.getRuntime().setMinimumHeapSize(NewSize);堆(HEAP)是VM中占用内存最多的部分,通常是动态分配的。堆的大小不是一成不变的,通常有一个分配机制来控制它的大小。比如初始的HEAP是4M大,当4M的空间被占用超过75%的时候,重新分配堆为8M大;当8M被占用超过75%,分配堆为16M大。倒过来,当16M的堆利用不足30%的时候,缩减它的大小为8M大。重新设置堆的大小,尤其是压缩,一般会涉及到内存的拷贝,所以变更堆的大小对效率有不良影响。MaxHeapSize,是堆内存的上限值,Android的缺省值是16M(某些机型是24M),对于普通应用这是不能改的。函数setMinimumHeapSize其实只是改变了堆的下限值,它可以防止过于频繁的堆内存分配,当设置最小堆内存大小超过上限值时仍然采用堆的上限值,对于内存不足没什么作用。setTargetHeapUtilization(floatnewTarget)可以设定内存利用率的百分比,当实际的利用率偏离这个百分比的时候,虚拟机会在GC的时候调整堆内存大小,让实际占用率向个百分比靠拢。在手机上进行了多次测试,确实不好使,在此,我断了改变内存限制的方法。第二:查找出现问题的原因。1,在网上搜索bitmap内存溢出,找到很多说是因为图片大小引起的此问题。观察我的资源文件,没有太大的图片,只是图片数量过多,有将近900张,分别找出一张最大的图片和几张比较大的图片,单独测试,没有发现问题。方法1排除。2,既然图片数量过多,突破点可能就是图片数量问题。于是分别找了200,400,600图片进行测试,在500左右的时候遇到错误,通过宝哥知道了将小图片整合存放到一张大图的方法,以此来减少图片的数量,但是仔细想想,加载成bitmap的时候还是要切割成小图生成bitmap,所以对此方法表示怀疑。由于以前没用过此方法,试试也无妨。所用到的工具是gdx—texturepackger,它只是一个工具,这里就不多说了。测试的最终结果是还是oom。方法2排除。3,现在看来,既然不是图片数量的问题,而且会在500张左右的时候报错,那就可能是占用内存大小的问题了,Android手机有内存限制,但是我的图片大小又大于这个限制,这让我头疼了很长时间,研究国外的一些文章,从中发现了一些有用的信息,这些信息能够加深你对Android的解析bitmap机制的理解,在此分享:AsofHoneycombBitmapdataisallocatedintheVMheap.作为蜂窝位图数据是在VM分配堆。)ThereisareferencetoitintheVMheap(whichissmall),buttheactualdataisallocatedintheNativeheapbytheunderlyingSkiagraphicslibrary.有一个引用在VM堆(小),但实际的数据是在本机堆分配由底层Skia图形库。Unfortunately,whilethedefinitionofBitmapFactory.decode…()saysthatitreturnsnulliftheimagedatacouldnotbedecoded,theSkiaimplementation(orrathertheJNIgluebetweentheJavacodeandSkia)logsthemessageyou’reseeing(“VMwon’tletusallocatexxxxbytes”)andthenthrowsanOutOfMemoryexceptionwiththemisleadingmessage“bitmapsizeexceedsVMbudget”.不幸的是,虽然BitmapFactory.decode的定义…()表示,它返回null如果图像数据不能解码,Skia实现(或者说JNI胶之间的Java代码和Skia)日志消息你看到(“VM不会让我们分配xxxx字节”),然后抛出一个OutOfMemory异常与误导信息”位图的大小超过VM预算”。TheissueisnotintheVMheapbutisratherintheNativeheap.这个问题不是在VM堆而是在本机堆。TheNatïveheapissharedbetweenrunningapplications,sotheamountoffreespacedependsonwhatotherapplicationsarerunningandtheirbitmapusage.本机堆是正在运行的应用程序之间共享,因此空闲空间的大小取决于其他运行程序,他们使用的位图。However,IhavefoundthatgetNativeHeapFreeSize()andgetNativeHeapSize()arenotreliable.然而,我发现getNativeHeapFreeSize()和getNativeHeapSize()是不可靠的。TheNativeheapsizevariesbyplatform.本机堆大小不同的平台。Soatstartup,wecheckthemaximumallowedVMheapsizetodeterminethemaximumallowedNativeheapsize.所以在启动时,我们检查最大允许VM堆大小来确定最大允许本机堆大小。“BitmapdataisnotallocatedintheVMheap”—itisallocatedontheVMheapasofHoneycomb“位图数据不是在VM分配堆”——这是VM分配的堆在蜂窝Yes.是的。AsofHoneycomb(v3.0),bitmapdataisallocatedontheVMheap.作为蜂窝(v3.0),位图数据堆上分配VM。SoalloftheaboveonlyappliestoGingerbread(v2.3.x)andbefore所以所有上述只适用于姜饼(v23x)和之前这些信息零零散散,但是不难发现,问题的原因就在于根据Android版本的不同,bitmapdata存放的位置是不同的,3.0以前是分配在nativeheap上,3.0以后是分配在VMheap上。
东莞市友贸实业有限公司_
2023-11-22 广告
2023-11-22 广告
第五代双倍数据速率DDR5双列直插式内存模块是一种高速、高性能的内存模块,适用于需要高带宽和低延迟的应用场景。与前几代内存模块相比,DDR5双列直插式内存模块具有更高的数据传输速率和更低的功耗,同时提供了更大的内存容量和更高的可靠性。在数据...
点击进入详情页
本回答由东莞市友贸实业有限公司_提供
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询