Android 中的位图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1945142/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bitmaps in Android
提问by Samuh
I have a few questions regarding Bitmap objects and memory and their general taxonomy.
我有一些关于位图对象和内存及其一般分类的问题。
- What is an in-memory or native bitmap?
- How is Bitmap memory different from Heap memory?
- 什么是内存位图或本机位图?
- 位图内存与堆内存有何不同?
回答by Trevor Johns
The memory that backs a Bitmap object is allocated using native code (malloc()
), rather than the Java new
keyword. This means that the memory is managed directly by the OS, rather than by Dalvik.
支持 Bitmap 对象的内存是使用本机代码 ( malloc()
) 而不是 Javanew
关键字分配的。这意味着内存由操作系统直接管理,而不是由 Dalvik 管理。
The only real difference between the native heap and Dalvik's heap is that Dalvik's heap is garbage collected, and the native one isn't.
本机堆和 Dalvik 的堆之间唯一真正的区别是 Dalvik 的堆是垃圾收集的,而本机的不是。
For these purposes though, here's not much difference. When your Bitmap object gets garbage collected, it's destructor will recycle the associated memory in the native heap.
但是,对于这些目的,这里没有太大区别。当您的 Bitmap 对象被垃圾收集时,它的析构函数将回收本机堆中的相关内存。
Source:
来源:
回答by hackbod
There is an important subtlety here: though Bitmap pixels are allocated in the native heap, some special tricks in Dalvik cause it to be accounted against the Java heap. This is done for two reasons:
这里有一个重要的微妙之处:虽然位图像素是在本机堆中分配的,但 Dalvik 中的一些特殊技巧导致它与 Java 堆相对应。这样做有两个原因:
(1) To control the amount of memory an application allocates this. Without the accounting, an application could allocate a huge amount of memory (since the Bitmap object itself is very small yet can hold on to an arbitrarily large amount of native memory), extending beyond the 16MB or 24MB heap limit.
(1) 为了控制应用程序分配的内存量。如果没有记帐,应用程序可能会分配大量内存(因为 Bitmap 对象本身非常小,但可以保留任意大量的本机内存),超出 16MB 或 24MB 堆限制。
(2) To help determine when to GC. Without the accounting, you could allocate and release references on say 100 Bitmap objects; the GC wouldn't run, because these objects are tiny, but they could in fact represent a large number of megabytes of actual allocations that is now not being GCed in a timely manner. By accounting these allocations against the Java heap, the garbage collector will run as it thinks memory is being used.
(2) 帮助确定何时进行 GC。没有会计,你可以分配和释放对 100 个 Bitmap 对象的引用;GC 不会运行,因为这些对象很小,但它们实际上可能代表大量的实际分配,现在没有及时进行 GC。通过针对 Java 堆计算这些分配,垃圾收集器将在它认为正在使用内存时运行。
Note that in many ways this is an implementation detail; it is very likely that it could change in the future, though this basic behavior would remain in some form since these are both important characteristics for managing bitmap allocations.
请注意,在许多方面,这是一个实现细节;它很可能在未来发生变化,尽管这种基本行为将保持某种形式,因为这些都是管理位图分配的重要特征。
回答by Dave Dopson
From deployments in the wild, I've found the following devices:
从野外部署中,我发现了以下设备:
Devices that limit to 16 MiB of java heap (bitmaps are nearly unlimited).- Devices that limit to 16 MiB of (java heap + native bitmap storage)
Devices that limit to 24 MiB of java heap (bitmaps are nearly unlimited).- Devices that limit to 24 MiB of (java heap + native bitmap storage)
限制为 16 MiB 的 Java 堆的设备(位图几乎是无限的)。- 限制为 16 MiB 的设备(Java 堆 + 本机位图存储)
限制为 24 MiB 的 Java 堆的设备(位图几乎是无限的)。- 限制为 24 MiB 的设备(Java 堆 + 本机位图存储)
24 MiB tends to be the high res devices, and can be detected with Runtime.getRuntime().maxMemory(). There's also 32MiB devices now, and some of the rooted phones have 64MiB by default. Previously, I confused my self several times trying to work out what was happening. I think all devices count bitmaps into the heap limit. But it's wildly difficult to make any sweeping generalizations about the android fleet.
24 MiB 往往是高分辨率设备,可以使用 Runtime.getRuntime().maxMemory() 检测到。现在也有 32MiB 的设备,一些 root 的手机默认有 64MiB。以前,我多次困惑自己,试图弄清楚发生了什么。我认为所有设备都将位图计入堆限制。但是要对 android 舰队做出任何全面的概括是非常困难的。
This is a VERY nasty issue on Android, and very confusing. This limit and it's behaviors are poorly documented, complicated, and extremely non-intuitive. They also vary across devices and OS versions, and have several known bugs. Part of the problem is that the limits are not precise - due to heap fragmentation, you will hit OOM well before the actual limit and must conservatively leave a meg or two of buffer. Even worse, I've got several devices where there is a native segfault (100% a bug in Android itself) that occurs before you get the java OOM exception, making it doubly important to never reach the limit since you can't even catch the native crash. For more details on my investigations, check out this post. In the same post, I explain how to measure usage against the limit and avoid crashes.
这在 Android 上是一个非常讨厌的问题,而且非常令人困惑。此限制及其行为记录不充分、复杂且非常不直观。它们也因设备和操作系统版本而异,并且有几个已知的错误。部分问题是限制不精确 - 由于堆碎片,您将在实际限制之前达到 OOM,并且必须保守地保留一两兆缓冲区。更糟糕的是,我有几个设备在你得到 java OOM 异常之前发生了一个本地段错误(100% 是 Android 本身的错误),这使得永远不会达到限制变得更加重要,因为你甚至无法捕捉本机崩溃。有关我的调查的更多详细信息,请查看此帖子。在同一篇文章中,我解释了如何根据限制衡量使用情况并避免崩溃。
The size of the java heap is Runtime.getRuntime().totalMemory().
java堆的大小是Runtime.getRuntime().totalMemory()。
There is no easy way to measure the size of the native bitmap storage. The overall native heap can be measure with Debug.getNativeHeapAllocatedSize(), but only the bitmaps count toward the limit (i think).
没有简单的方法可以测量本机位图存储的大小。可以使用 Debug.getNativeHeapAllocatedSize() 测量整体本机堆,但只有位图计入限制(我认为)。
回答by Pratik Deogade
We can increase the heap size by using android:largeheap="true"
in your manifest file. This will solve your some problem.
我们可以通过android:largeheap="true"
在您的清单文件中使用来增加堆大小。这将解决您的一些问题。