OOM问题

作者: 主音King | 来源:发表于2020-01-06 09:58 被阅读0次

体现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问题的原因之后,我们对于线上的问题

相关文章

  • (12)Redis大KEY定位及优化

    问题:出现OOM报错: OOM command not allowed when used memory > ‘m...

  • OOM问题

    1、什么是oom当前占用的内存加上我们申请的内存资源超过了Dalvik虚拟机的最大内存限制就会抛出的Out Of ...

  • OOM问题

    OOM是开发中会经常遇见的一类问题,其中很多原因是可以在写代码阶段就可以排查出来的,本文结合之前解决的OOM的问题...

  • OOM问题

    体现APP稳定性的重要数据就是Crash率,众多crash种最棘手最难定位的是OOM问题。APP中所有的内存泄漏都...

  • OOM问题

    什么是oom? 当前程序占用的内存加上我们申请的内存资源超过了Dalvik虚拟机的最大内存限制,就会抛出Out o...

  • 一次解决Android OOM的经历

    OOM OOM(Out Of Memory)是Android应用开发中相信每个人都遇到过的问题,而OOM在cras...

  • Android性能调优:记一次解决OOM的经历

    OOM OOM(Out Of Memory)是Android应用开发中相信每个人都遇到过的问题,而OOM在cras...

  • 全方位性能调优:一次解决Android OOM的经历

    OOM OOM(Out Of Memory)是Android应用开发中相信每个人都遇到过的问题,而OOM在cras...

  • Java服务,内存OOM问题如何快速定位

    Java服务,内存OOM问题如何快速定位 Java服务出现了OOM(Out Of Memory)问题,总结了一些相...

  • ResourceExhaustedError

    问题:ResourceExhaustedError (see above for traceback): OOM ...

网友评论

      本文标题:OOM问题

      本文链接:https://www.haomeiwen.com/subject/gngsgctx.html