文章详细分析了Android应用为什么会抛出OutOfMemoryError,以及在哪些情况下会发生这种情况。以下是文章的主要内容概述:
-
OOM异常的触发:在Java层,只有
java.lang.OutOfMemoryError
这一个Throwable定义,而抛出这个异常的行为是由JNI层触发的,具体是通过Thread::ThrowOutOfMemoryError
函数。 -
不常见的OOM情况:文章列举了一些不常见的OOM情况,例如在ClassPreDefine时的
MakeSingleDexFIle
,通过JNI的NewStringUTF
分配超长字符串,JavaUnsafe
分配内存失败,以及在创建Java线程时的Thread#start
。 -
常见的OOM情况:文章指出,最常见的OOM发生在堆内存分配过程中,特别是在
Heap::AllocateInternalWithGc
中。如果在AllocObjectWithAllocator
函数里的TryToAllocate
分配失败,会尝试进行垃圾回收(GC)后再重新分配。 -
内存分配的步骤:文章详细描述了内存分配的步骤,包括在GC进行时等待GC结束、GC结束后尝试分配内存、如果失败再次进行GC但不清除软引用、如果还失败则进行更强力的GC清除软引用等。如果所有尝试都失败,则最终会抛出OOM异常。
-
内存优化机制:文章总结了一些内存优化的思路,如减少不合理的内存分配和占用、及时释放内存避免内存泄漏、防止虚拟内存泄漏等。此外,文章还提到了通过
inlinehook
修改Android 8以下Bitmap
的内存分配来减少Java堆内存占用的方法。 -
内存管理的重要性:文章强调了内存管理的重要性,指出内存缺乏治理不仅可能导致直接OOM,还可能引发频繁的GC,影响APP的性能指标,如ANR率、Crash率和卡顿。
这篇文章对于Android开发者来说是非常有价值的,因为它不仅解释了OOM的原因和机制,还提供了一些实用的内存优化技巧和建议,有助于开发者更好地管理和优化Android应用的内存使用。