Android中的位图
我有一些关于位图对象和内存及其一般分类的问题。
- 什么是内存或本地位图?
- 位图内存与堆内存有什么不同?
支持Bitmap对象的内存是使用本地代码( malloc()
)分配的,而不是Java new
关键字。 这意味着内存由操作系统直接pipe理,而不是由Dalvikpipe理。
本地堆和Dalvik堆之间唯一真正的区别是Dalvik的堆是垃圾回收,而本地堆不是。
尽pipe如此,这里没有太大的区别。 当你的Bitmap对象被垃圾收集时,它的析构函数会回收本地堆中相关的内存。
资源:
- http://osdir.com/ml/AndroidDevelopers/2009-03/msg00023.html
- 安卓平台/框架/基/graphics/ JAVA /安卓/graphics/ Bitmap.java
- 机器人:平台/框架/碱/核心/ JNI /机器人/graphics/ Bitmap.cpp
这里有一个很重要的细微之处:尽pipeBitmap像素被分配在本地堆中,但Dalvik中的一些特殊技巧使得它被计入Java堆中。 这是由于两个原因:
(1)控制应用程序分配的内存量。 没有会计,应用程序可以分配大量的内存(因为Bitmap对象本身非常小,可以容纳任意大量的本机内存),扩展超过了16MB或24MB堆的限制。
(2)帮助确定何时进行GC。 没有会计,你可以分配和释放所说的100个位图对象的引用; GC不会运行,因为这些对象很小,但实际上它们可能代表了大量实际分配的兆字节,而这些分配现在没有及时进行。 通过对Java堆计算这些分配,垃圾收集器将按照它认为正在使用的内存运行。
请注意,在许多方面这是一个实现细节; 它很可能会在将来发生变化,尽pipe这种基本的行为仍然会以某种forms存在,因为这些都是pipe理位图分配的重要特征。
从野外部署,我发现了以下设备:
-
限制在java堆的16 MiB的设备(位图几乎是无限的)。 - (java堆+本地位图存储)限制为16 MiB的设备
-
限制为24MB Java堆的设备(位图几乎是无限的)。 - (java堆+本地位图存储)限制为24 MiB的设备
24 MiB往往是高分辨率设备,可以使用Runtime.getRuntime()。maxMemory()来检测。 现在还有32MiB设备,一些根植的手机默认有64MiB。 以前,我多次困惑自己,试图弄清楚发生了什么。 我认为所有设备都将位图计入堆限制中。 但是对于机器人队伍的概括是非常困难的。
这是一个非常讨厌的问题在Android上,非常混乱。 这种限制和它的行为logging不完善,复杂而且非常不直观。 它们在不同的设备和操作系统版本上也有所不同,并且有几个已知的错误 部分问题是限制不准确 – 由于堆碎片,你会在实际限制之前打到OOM,并且必须保守地留下一两个缓冲区。 更糟糕的是,在出现java OOMexception之前,我有几个设备出现了本地段错误(100%是Android本身的错误),因此永远达不到极限是非常重要的,因为您甚至无法捕捉本机崩溃。 有关我的调查的更多细节,请查看这篇文章 。 在同一篇文章中,我解释了如何衡量使用限制和避免崩溃。
java堆的大小是Runtime.getRuntime()。totalMemory()。
没有简单的方法来测量本地位图存储的大小。 整个本机堆可以用Debug.getNativeHeapAllocatedSize()来衡量,但只有位图计算的极限(我认为)。
我们可以通过在清单文件中使用android:largeheap="true"
来增加堆大小。 这将解决你的一些问题。
- 如何在Android中通过URL加载ImageView?
- JNI位图操作,帮助避免使用大图像时的OOM
- 使用entity framework6从SQL Server保存并检索图像(二进制)
- Android:从图库加载的位图在ImageView中旋转
- canvas:试图在Android中使用回收的位图android.graphics.Bitmap
- BitmapFactory.decodeResource在Android 2.2中返回一个可变的位图,在Android 1.6中返回一个不可变的位图
- 将BitmapImage转换为位图,反之亦然
- OutOfMemoryError:位图大小超过虚拟机预算: – Android
- 如何将字节数组转换为位图