🚀 优质资源分享 🚀
学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
🧡 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