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