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.
  ...
}

在出现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

上面这段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 app 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值