• Android OOM 问题探究 -- 从入门到放弃


    🚀 优质资源分享 🚀

    学习路线指引(点击解锁) 知识定位 人群定位
    🧡 Python实战微信订餐小程序 🧡 进阶级 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
    💛Python量化交易实战💛 入门级 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

    一、前言

    最近客户反馈了一些OOM的问题,很早之前自己也有简单了解过OOM的知识,但时间久远,很多东西都记不清了。

    现在遇到这个OOM问题,也即趁此搜索了一些资料,对OOM问题做一些探究,把资料记录于此,一遍后续查阅。本文内容大量借鉴参考了网络上经典文章的内容,站在巨人的肩膀上登高望远!

    注:以下分析基于 Android R source

    二、OOM问题的可能原因

    网络上可以搜索到很多的解释,都很详细,我在此也做一个简单的总结,当然可能不全面,仅供学习参考

    Android系统中,OutOfMemoryError这个错误是怎么被系统抛出的?在代码进行搜索可以看到

    重点关注下面两点

    ✔️ 堆内存分配失败时的OOM  ==   /art/runtime/gc/heap.cc

    ✔️ 创建线程失败时的OOM     ==   /art/runtime/thread.cc

    三、OOM – 堆内存分配失败

    在source code中我们可以看到,当堆内存分配失败时,会抛出一些典型的log,如下代码

    void Heap::ThrowOutOfMemoryError(Thread* self, size_t byte_count, AllocatorType allocator_type) {
      ...
      std::ostringstream oss;
      size_t total_bytes_free = GetFreeMemory();
      oss << "Failed to allocate a " << byte_count << " byte allocation with " << total_bytes_free
          << " free bytes and " << PrettySize(GetFreeMemoryUntilOOME()) << " until OOM,"
          << " target footprint " << target_footprint_.load(std::memory\_order\_relaxed)
          << ", growth limit "
          << growth_limit_;
      // If the allocation failed due to fragmentation, print out the largest continuous allocation.
      ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在出现OOM问题时,logcat中应该会看到类似下面的信息输出

    08-19 11:34:53.860 28028 28028 E AndroidRuntime: java.lang.OutOfMemoryError: Failed to allocate a 20971536 byte allocation with 6147912 free bytes and 6003KB until OOM, target footprint 134217728, growth limit 134217728
    
    • 1

    上面这段logcat的大概解释:想要去分配 20971536 bytes的heap memory,但时app剩余可用的free heap只有6147912 bytes,而且当前app最大可分配的heap是134217728 bytes

    堆内存分配失败的原因可以分两种情况:1. 超过APP进程的heap内存上限 与 2. 没有足够大小的连续地址空间

    3.1 超过APP进程的内存上限

    Android设备上java虚拟机对单个应用的最大内存分配做了约束,超出这个值就会OOM。由Runtime.getRuntime.MaxMemory()可以得到Android中每个进程被系统分配的内存上限,当进程占用内存达到这个上限时就会发生OOM,这也是Android中最常见的OOM类型。


    Android系统有如下约定:

    • /vendor/build.prop有定义属性值来对单个应用的最大内存分配做约束

    dalvik.vm.heapgrowthlimit 常规app使用的参数

    dalvik.vm.heapsize 应用在AndroidManifest.xml设置了android:largeHeap="true",将会变成大应用的设置

    • 代码中也可以使用如下API来获取内存限制的信息

    ActivityManager.getMemoryClass() 常规app最大可用的堆内存,对应 dalvik.vm.heapgrowthlimit;

    **ActivityManager.getLargeMemoryClass()**应用在AndroidManifest.xml设置了android:largeHeap=“true”,将会变成大应用时最大可用的堆内存,对应dalvik.vm.heapsize;

    Runtime.getRuntime().maxMemory()  可以得到Android中每个进程被系统分配的内存上限,等于上面的两个值之一;


    如下是一段简单的代码来演示这种类型的OOM:

    private void testOOMCreatHeap(Context context) {
        ActivityManager activityManager =(ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
        Log.d("OOM\_TEST", "app maxMemory = " + activityManager.getMemoryClass() + "MB");
        Log.d("OOM\_TEST", "large ap
    • 1
    • 2
    • 3
  • 相关阅读:
    Linux防火墙配置
    Hold the door! 基于Django建立基础框架
    单词拼写引起的错误_username_uername
    MySQL 8.0 Clone Plugin 详解
    解决cocoapods下载hermes太慢的问题
    math_数集(数集符号)和集合论
    java计算机毕业设计河池市旅游信息系统MyBatis+系统+LW文档+源码+调试部署
    axios——503响应超时重复多次请求——技能提升
    SpringBoot自动装配 Spring相关 常用设计模式 双亲委派 MongoDB Redis 适配器模式与策略模式
    张量-类型转换函数
  • 原文地址:https://blog.csdn.net/u012804784/article/details/126446677