我有一些关于Bitmap对象和内存及其一般分类的问题。
答案 0 :(得分:33)
使用本机代码(malloc()
)而不是Java new
关键字分配支持Bitmap对象的内存。这意味着内存由操作系统直接管理,而不是由Dalvik管理。
本机堆和Dalvik堆之间唯一真正的区别是Dalvik的堆是垃圾收集的,本地堆不是。
出于这些目的,这里没有太大的区别。当您的Bitmap对象被垃圾收集时,它的析构函数将回收本机堆中的相关内存。
来源:
答案 1 :(得分:32)
这里有一个重要的微妙之处:虽然Bitmap像素是在本机堆中分配的,但Dalvik中的一些特殊技巧会导致它与Java堆相对应。这样做有两个原因:
(1)控制应用程序分配的内存量。如果没有计算,应用程序可以分配大量内存(因为Bitmap对象本身非常小但可以保留到任意大量的本机内存),超出了16MB或24MB的堆限制。
(2)帮助确定何时进行GC。如果没有会计,您可以在100个Bitmap对象上分配和释放引用; GC不会运行,因为这些对象很小,但它们实际上可能代表了大量的兆字节实际分配,现在没有及时进行GC。通过将这些分配与Java堆进行核算,垃圾收集器将在它认为正在使用内存时运行。
请注意,在很多方面,这是一个实现细节;它很可能在未来发生变化,尽管这种基本行为将保持某种形式,因为这些都是管理位图分配的重要特征。
答案 2 :(得分:12)
从野外部署中,我发现了以下设备:
24 MiB往往是高分辨率设备,可以使用Runtime.getRuntime()。maxMemory()检测。现在还有32MiB设备,默认情况下,一些有根电话的设备有64MiB。以前,我曾经多次试图弄清楚发生了什么。我认为所有设备都将位图计入堆限制。但是对于机器人舰队进行任何全面的概括都非常困难。
这在Android上是一个非常讨厌的问题,而且非常令人困惑。这个限制和它的行为记录很少,很复杂,而且非常不直观。它们也因设备和操作系统版本而异,并且有几个已知的错误。部分问题是限制不准确 - 由于堆碎片,你将在实际限制之前很好地击中OOM,并且必须保守地留下一两或两个缓冲区。更糟糕的是,我有几个设备存在本地段错误(100%是Android本身的错误),在你获得java OOM异常之前就已经发生了,因为你甚至无法捕获它,因此永远不会达到极限是非常重要的本机崩溃。有关我的调查的更多详细信息,请查看this post。在同一篇文章中,我将解释如何根据限制来衡量使用情况并避免崩溃。
java堆的大小是Runtime.getRuntime()。totalMemory()。
没有简单的方法来衡量本机位图存储的大小。可以使用Debug.getNativeHeapAllocatedSize()来测量整个本机堆,但只有位图计数到极限(我认为)。
答案 3 :(得分:-1)
我们可以在清单文件中使用android:largeheap="true"
来增加堆大小。这将解决您的一些问题。