bie地图内存溢出

biemap内存溢出

android系统的手机在系统底层指定了堆内存的上限值,大部分手机的缺省值是16MB,不过也有些高配置的机型是24MB的,所以我们的程序在申请内存空间时,为了确保能够成功申请到内存空间,应该保证当前已分配的内存加上当前需要分配的内存值的总大小不能超过当前堆的最大内存值。由于内存管理上将外部内存完全当成了当前堆的一部分,也就是说Bitmap对象通过栈上的引用来指向堆上的Bitmap对象,而堆上的Bitmap对象又对应了一个使用了外部存储的native图像,也就是实际上使用的字节数组byte[]来存储的位图信息,因此解码之后的Bitmap的总大小就不能超过8M了。

解决这类问题的最根本的,最有效的办法就是,使用完bitmap之后,调用bitmap对象的recycle()方法释放所占用的内存,以便于下一次使用。

下面是网上找到的一些常用的优化办法,但是基本上都不能从本质上解决问题。

1.设置系统的最小堆大小: 

int newSize = 4 * 1024 * 1024 ; //设置最小堆内存大小为4MB  
VMRuntime.getRuntime().setMinimumHeapSize(newSize);  
VMRuntime.getRuntime().setTargetHeapUtilization(0.75); // 设置堆内存的利用率为75%  

 补充说明:堆(HEAP)是VM中占用内存最多的部分,通常是动态分配的。堆的大小不是一成不变的,当堆内存实际的利用率偏离设定的值的时候,虚拟机会在GC的时候调整堆内存大小,让实际占用率向个百分比靠拢。比如初始的HEAP是4M大小,当4M的空间被占用超过75%的时候,重新分配堆为8M大;当8M被占用超过75%,分配堆为16M大。倒过来,当16M的堆利用不足30%的时候,缩减它的大小为8M大。重新设置堆的大小,尤其是压缩,一般会涉及到内存的拷贝,所以变更堆的大小对效率有不良影响。

2.对图片的大小进行控制

BitmapFactory.Options options = new BitmapFactory.Options();  
options.inSampleSize = 2; //图片宽高都为原来的二分之一,即图片为原来的四分之一  
Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/a.jpg",options); 
//或bitmap = BitmapFactory.decodeStream(new FileInputStream(file),null,options);

 补充说明:这种方法只是对图片做了一个缩放处理,降低了图片的分辨率,在需要保证图片质量的应用中不可取。

3.

BitmapFactory.Options options = new BitmapFactory.Options();  
options.inTempStorage = new byte[1024*1024*5]; //5MB的临时存储空间  
Bitmap bm = BitmapFactory.decodeFile("/mnt/sdcard/a.jpg",options);  

 补充说明:从创建Bitmap的C++底层代码BitmapFactory.cpp中的处理逻辑来看,如果option不为null的话,那么会优先处理option中设置的各个参数,假设当前你设置option的inTempStorage为1024*1024*4(4M)大小的话,而且每次解码图像时均使用该option对象作为参数,那么你的程序极有可能会提前失败,经过测试,如果使用一张大小为1.03M的图片来进行解码,如果不使用option参数来解码,可以正常解码四次,也就是分配了四次内存,而如果使用option的话,就会出现内存溢出错误,只能正常解码两次。Options类有一个预处理参数,当你传入options时,并且指定临时使用内存大小的话,Android将默认先申请你所指定的内存大小,如果申请失败,就会先抛出内存溢出错误。而如果不指定内存大小,系统将会自动计算,如果当前还剩3M空间大小,而解码只需要2M大小,那么在缺省情况下将能解码成功,而在设置inTempStorage大小为4M的情况下就将出现内存溢出错误。所以,通过设置Options的inTempStorage大小也不能从根本上解决大图像解码的内存溢出问题。

总之再做android开发时,出现内存溢出是属于系统底层限制,只要解码需要的内存超过系统可分配的最大内存值,那么内存溢出错误必然会出现。