| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> 从 Android OOM监控与分析 -> 正文阅读 |
|
[移动开发]从 Android OOM监控与分析 |
简单介绍What's OOM?全称“Out Of Memory”,指的是内存超出了限制,抛出的一个异常。 Why OOM?
常见的OOM类型为java.lang.OutOfMemoryError: Java heap space ,Java堆内存溢出。 一般的解决办法Java抛出来的OutOfMemoryError,和其他崩溃一样也会有其堆栈信息。如下
通过堆栈信息能确认到崩溃那一刻调用的方法,在本例子中可以看到是解析加载图片资源时出错。但是我们并不知道是哪个图片,而且这图片并不是真正的问题所在,因为这个时候内存已经达到了接近崩溃的边缘,做任何分配的操作都会导致OOM。 所以在解决该类问题时,最常用的办法就是heapdump,这是java虚拟机上的应用解决OOM的通用办法。 将OOM时的内存dump下来后,通过Memery Analyzer(?MAT)工具打开进行分析,MAT的使用可以参考[分析指南] 如何dump内存 针对debuggable的应用,调用
对于release的应用,只能Java代码中使用
Android获取到的内存文件不能直接用于MAT分析,需要通过Android SDK提供的工具进行转换
上面就是一般的分析流程,而我们需要的是一套完善的更加自动化的方案。 有几个需要解决的问题
监控阶段端上内存自监控为什么要自己监控内存?因为在全局异常捕获中收到OOM error信息时再去做内存dump,会有一定的失败率。dump还未完成,程序就已经崩掉,所以如果能在抛出OOM error,及早发现可能OOM,这个时候去做一些处理,能有更多的操作空间。 具体方案为在监控开始时,起一个定时线程,每隔3秒进行一个内存监测
端上内存主动释放当能监控到应用运行过程中的占用比时,能做的事情就比较多了,可以选择在高内存占比时,先做一些释放操作,在基线里面目前做了释放了两个模块,图片和Card,因为这两个模块是使用内存的大头。 现在的策略是在不同的占比做不同程度的内存释放。 系统也会监控内存,提供了内存的回调
系统的这两个回调也应该做一些释放,这个和我们的监控不冲突,或者说是互补,因为一个是系统内存,一个是应用内存。 端上dump时机因为dump是非常影响用户体验的,最好要在真正需要dump的时候进行 当内存达到97%(这个是目前经验值)时,我们判断其已经接近OOM,是不是dump时机,还不能保证。因为可能有20%的内存在下次gc就能被回收掉 为了在gc之后再看看情况,流程中会主动调用System.gc(),熟悉的同学都知道gc()并不是你调用就马上执行,这是由虚拟机决定的。 通过查找资料,并没有直接的方式去判断虚拟机是否执行了我们的GC,我们也必须在GC后看看内存是否还在97%,这表示内存已达到了无可释放的程度。 现在是通过间接的方式来观察GC情况,Java引用类型分为四种强引用,软引用,弱引用,虚引用,每个的描述我就不介绍了,用到的就是弱引用,弱引用特点是当遇到gc时就会立马回收掉。 在首次内存达到97%的时候,创建一个弱引用对象作为哨兵,然后调用gc。当下次查看内存,发现哨兵被回收且内存继续保持97%的时候,我们就可以做dump操作了。 dump的性能问题 dump会导致应用进程冻结一段时间,会给用户带来比较明显的卡,经过测试在android 7.0以后的系统能降低到5s以内,而7.0以前的系统会卡10s及10s以上,所以在线上运行是我们是采样并且过滤版本的方式,样本控制的尽量少,以发现问题为主要目的。 内存泄漏加成除了监控内存做相应的处理,OOM也会配合内存泄漏监控,为后续的分析问题提供更多的信息 简单介绍下内存泄漏监控 首先registerActivityLifecycleCallbacks注册Activity的生命周期回调 然后在onActivityCreated,onActivityDestroyed记录每个Activity的开始和中止 当一定时间后发现有Activity已经被destroyed但是还未被回收,便认为泄漏,在应用要dump的同时会将该泄漏信息保留下来,具体的可以参考LeakCanary发现原理 图1:?监控,及发生OOM后做的响应应急处理流程 处理阶段端上问题自动发现主要是依赖的二次启动来处理,在dump完之后应用大概率会崩溃,而分析那些逻辑主要在第二次启动 第二次启动后发现有dump的文件,便开始进入处理分析流程,这里是另外起了一个:memery进行执行 分析流程有如下图三种处理方式 图2 问题分析 解析泄漏路径如果同时有泄漏信息,直接调用Leakcanary进行路径分析(原理参考LeakCanary的分析原理),并投递 大内存解析如果主要分析dump信息中包含的大内存文件,关于这一点可以参考OOMTrack的PPT的介绍 压缩上传当未发现泄漏信息时,会有随机抽取50%的样本采取压缩上传的方式,因为大内存解析并不能准确发现所有问题,这个时候就能手动导入MAT进行更全面的分析了。 展示Qmas数据展示上面两张图绿色部分的投递,最终都能在Qmas中查看 Qmas对应分析入口地址:http://qmas.qiyi.domain/embed/apm?mod=crash?-> 内存分析 -> OOM分析 后续遗留问题现在OOM的分析有三个问题待后续解决,dump带来的卡住时间问题,分析耗时问题,文件即使压缩也很大的问题 目前业内也已经有解决方案,其实质是裁剪dump的冗余信息 后续方案利用xHook,在执行dump的准备阶段,我们会调用Native层的open函数获得一个文件句柄,但实际执行时会进入到Hook层中,然后将返回的FD保存下来,用作write时匹配。 在dump开始时,系统会不断的调用write函数将内容写入到文件中。由于我们的Hook是以so为目标的,系统运行时也会有许多写文件的操作,所以我们需要对前面保存的FD进行匹配。若FD匹配成功则进行裁剪,否则直接调用origin-write进行写入操作。 裁剪后的文件可以变得很小,而且因为dump的io负担变小,也能极大的减少dump卡住时间,并且分析耗时也会随着文件变小而减少 通过这种方式,以上三个问题都能很好的优化 但是确定哪些内容需要裁剪,裁剪后如何再次解析,如何兼容MAT工具,都需要投入一定的成本去完成,目前还未计划支持。 可参考的文章Probe:Android线上OOM问题定位组件 基线APM内存分析接入?APM 内存监控分析 |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 7:40:21- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |