OOM问题

体现APP稳定性的重要数据就是Crash率,众多crash种最棘手最难定位的是OOM问题。APP中所有的内存泄漏都会慢慢累积在内存中,最有就容易导致OOM。


Android中OOM类型

Android虚拟机最终抛出OutOfMemoryError代码在/art/runtime/thread.cc

void Thread::ThrowOutOfMemoryError(const char* msg)
参数 msg 携带了 OOM 时的错误信息

堆内存分配失败
系统源码在/art/runtime/gc/heap.cc

void Heap::ThrowOutOfMemoryError(Thread* self, size_t byte_count, AllocatorType allocator_type)
抛出时的错误信息:
oss << "Failed to allocate a " << byte_count << " byte allocation with " << total_bytes_free  << " free bytes and " << PrettySize(GetFreeMemoryUntilOOME()) << " until OOM";

也可以分为不同的两种类型:
1、为对象分配内存时达到进程的内存上限。有Runtime.getRuntime.MaxMemory()可以得到Android中每个进程被系统分配的内存上限,当进程占用内存达到这个上限就会发生OOM。
2、没有足够大小的连续地址空间。进程中存在大量的内存碎片导致的,堆栈信息比第一种OOM堆栈多出一段信息:

failed due to fragmentation (required continguous free "<< required_bytes << " bytes for a new buffer where largest contiguous free " <<  largest_continuous_free_pages << " bytes)"; 其详细代码在art/runtime/gc/allocator/rosalloc.cc中,这里不作详述。

创建线程失败
系统源码:/art/runtime/thread.cc

void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_size, bool is_daemon)
抛出时的错误信息:
    "Could not allocate JNI Env"
  或者
    StringPrintf("pthread_create (%s stack) failed: %s", PrettySize(stack_size).c_str(), strerror(pthread_create_result)));

Android创建线程,中两个关键节点创建JNIEnv结构体和创建线程,均有可能抛出OOM。

创建线程过程

创建JNI失败
创建JNIEnv可以归为两个步骤:
通过Android的匿名共享内存分配4KB一个page内核态内存。
再通过Linux的mmap调用映射到用户态虚拟内存地址空间。
第一步创建共享内存时,需要打开/dev/ashmem文件,所以需要一个FD(文件描述符)。此时,如果创建FD数已经达到上限,会导致创建JNIEnv失败,抛出错误:

E/art: ashmem_create_region failed for 'indirect ref table': Too many open files
java.lang.OutOfMemoryError: Could not allocate JNI Env
  at java.lang.Thread.nativeCreate(Native Method)
  at java.lang.Thread.start(Thread.java:730)

第二步调用mmap时,如果进程虚拟内存地址空间耗尽会导致JNIEnv失败,抛出异常信息

E/art: Failed anonymous mmap(0x0, 8192, 0x3, 0x2, 116, 0): Operation not permitted. See process maps in the log.
java.lang.OutOfMemoryError: Could not allocate JNI Env
  at java.lang.Thread.nativeCreate(Native Method)
  at java.lang.Thread.start(Thread.java:1063)

分析清楚OOM问题的原因之后,我们对于线上的问题

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一件事、一份工作,重复一万小时不是刻意练习,只有在过程中不断提升改进,坚持每天进步一点点,才能蜕变成不一样的自己,...
    曲同宁阅读 62评论 0 0
  • 不下雪的″大雪”,听到这个题目大家定会感到难以理解。我乍看到这一首小诗以此为题时也深受同感。这是每周四、周...
    朱雪玲阅读 391评论 0 2
  • 人们说16岁是一个花一样的年纪,要好好珍惜,这个年纪我认识啦许多朋友,做啦许多想做的事,16岁的青春,我经历了许多...
    海贼凯阅读 153评论 1 0