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

    相关文章

      网友评论

          本文标题:OOM问题

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