如何解读Android发生OutOfMemory异常时的报错日志信息?
Android OOM报错日志字段详解
你遇到的报错日志原文如下:
Failed to allocate a 24 byte allocation with 294656 free bytes and 287KB until OOM, target footprint 268435456, growth limit 268435456; failed due to fragmentation (largest possible contiguous allocation 114556928 bytes)
以下是三个问题的对应解答:
1. 剩余可用空间足够却分配失败的原因
这段日志的各字段含义:
294656 free bytes:当前Java堆中所有零散空闲内存的总大小约为287KB287KB until OOM:当前堆如果再扩容287KB就会触碰到系统给应用设定的堆内存上限
分配失败的核心原因是内存碎片:总空闲内存是堆里多个不连续小内存块的总和,没有任何一块连续的内存块能满足本次分配需求。就算你只申请24字节,加上Android ART虚拟机的对象头开销、内存对齐要求,实际需要的连续内存远大于24字节,刚好当前没有符合要求的连续块,就会触发分配失败。
2. 内存碎片相关字段的含义
failed due to fragmentation:明确本次OOM的直接诱因是内存碎片,不是总内存耗尽largest possible contiguous allocation 114556928 bytes:当前堆中能找到的最大一块连续空闲内存约为109MB
你提到的256MB是应用堆的总上限,不是当前空闲内存的总大小。此时堆已经被应用占用了大部分,剩余的空闲内存被已使用的内存块切割成了大量小碎块,最大的整块只有109MB。
这里的「连续」指虚拟地址空间层面的连续。Android上所有Java对象的分配都要求占用一块连续的虚拟地址空间,哪怕物理内存足够,虚拟地址不连续也无法用于同一次对象分配。
3. 堆大小相关字段的含义
268435456换算后是256MB,两个数值相等说明当前应用堆已经增长到了最大上限,无法再扩容:
target footprint:ART虚拟机当前规划的堆内存总占用规模growth limit:系统给当前应用分配的Java堆最大可增长上限,该值由设备硬件配置、应用是否开启largeHeap开关共同决定
该数值仅指代Java/Kotlin代码可直接操作的应用堆大小,不包含存放dex/so/oat的代码堆、Native堆、图形缓冲区等其他进程内存区域。
内容的提问来源于stack exchange,提问作者H.Kim
相关产品推荐
相关产品推荐

