【问题标题】:Why don't these memory allocation numbers add up?为什么这些内存分配数字不加起来?
【发布时间】:2012-02-18 04:53:51
【问题描述】:

我在我的 adb logcat 窗口中看到以下内容:

01-24 14:40:56.916: E/dalvikvm-heap(24727): 1957200-byte external allocation too large for this process.
01-24 14:40:56.966: E/GraphicsJNI(24727): VM won't let us allocate 1957200 bytes
01-24 14:40:56.976: E/dalvikvm(24727): OutOfMemory: max: 50331648(49152 K), total: 39985120(39047 K), alloc: 33659240(32870 K), extAlloc: 8993870(8783 K)

我不明白为什么这些数字不加起来(或者我只是不明白这是如何工作的)。我看到 OutOfMemory: max 48MB 基本上——我认为这是最大堆大小。不确定在这种情况下“总计”是什么意思,但看起来大约 39MB。它在分配 2MB 时失败,我真的不明白为什么它失败了,应该有 9MB 可用......我在这里误解了什么?

【问题讨论】:

    标签: android memory out-of-memory


    【解决方案1】:

    欢迎来到堆碎片的奇妙世界。简而言之,您需要一块连续的内存来满足分配,而不仅仅是足够的空闲字节。

    例如,想象一个 1MB 的空堆。现在想象一下,在这 1MB 的中间是一个 1K 的分配。即使您有 99.9% 的可用空间,您也不能分配超过 500K 的任何空间,因为它必须是连续的。移动 1K 分配,您可以分配更多,但在病态的情况下,您最终可能拥有比您可以分配的更多的可用内存。

    对于您的情况,我敢打赌,如果您尝试进行 2000 次 1K 分配,效果会很好。这会让您知道您是否正在处理碎片或其他问题。

    【讨论】:

    • 所以必须有办法重新配置碎片化的内存。 System.gc() 会这样做吗?
    • GC 可以减少一些碎片,但并不是所有的内存分配都可以移动。例如,当前用于调用操作系统的缓冲区无法移动。
    • 那么另外一件事就是这个东西应该支持一个48MB的堆(至少根据Runtime.maxMemory(),所以它为什么不自动增加堆的大小来适应新的分配?
    • 这是 Android 限制:stackoverflow.com/questions/5350465/…
    猜你喜欢
    • 2012-11-08
    • 2017-05-03
    • 1970-01-01
    • 2020-10-26
    • 2014-09-14
    • 2021-03-02
    • 2018-11-06
    • 2012-01-20
    • 1970-01-01
    相关资源
    最近更新 更多