美文网首页
说说内存溢出?

说说内存溢出?

作者: Joseph_L | 来源:发表于2019-11-19 10:38 被阅读0次

    哪些情况下会导致oom问题?

    基本概念

    首先明确一点,内存泄漏和内存溢出是不同的,但是过多的内存泄漏会导致内存溢出。

    根据 java 的内存模型,会出现内存溢出的内存有堆内存、方法区内存、虚拟机栈内存、native方法区内存,一般说的 OOM 基本都是针对堆内存。

    堆内存溢出的根本原因有两种:

    1. app 进程内存达到上限
    2. 手机可用内存不足

    需要注意的是,手机可用内存不足一般是硬件原因,所以我们重点应该解决的是app的内存达到上限的问题。

    具体原因

    App 内存达到上限的原因也有两点:

    1. 应用申请内存的速度超出 gc 释放内存的速度

      • 往内存中加载超大文件
      • 循环创建大量对象
    2. 内存出现泄漏,gc无法回收泄漏的内存,导致可用内存越来越少,直至超过了应用的可用内存

      一般申请内存的速度超出gc释放内存基本不会出现,内存泄漏才是出现问题的关键所在

      • 资源对象没关闭造成的内存泄漏(如: Cursor、File等)
      • 全局集合类强引用没清理造成的内存泄漏(特别是 static 修饰的集合)
      • 接收器、监听器注册没取消造成的内存泄漏,如广播,EventsBus
      • Activity 的 Context 造成的泄漏
      • 单例中的static成员间接或直接持有了activity的引用
      • 非静态内部类持有父类的引用,如非静态 handler 持有 activity 的引用

    优化方向

    根据之前的分析,可以发现主要的问题在于应用可用内存较少,不良的代码习惯以及操作不当导致的内存泄漏。所以,相对应的有四个优化方向。

    1. 为应用申请更大内存,把 manifest 上的 largdgeheap 设置为 true;

    2. 优化内存的使用,减少大内存的开销

      • 使用优化后的集合对象,比如 SpaseArray;

      • 使用微信的 mmkv 替代 sharedpreference;

      • 对于经常打 log 的地方使用 StringBuilder 来组拼,替代 String 拼接;

        直接使用String会创建销毁多个实例,对性能有影响,StringBuffer只会一直操作同一个StringBuffer对象,就优化了内存使用

      • 统一带有缓存的基础库,特别是图片库,如果用了两套不一样的图片加载库就会出现2个图片各自维护一套图片缓存,无形中就加大了内存开销;

      • 给 ImageView 设置合适尺寸的图片,列表页显示缩略图,查看大图显示原图;

      • 优化业务架构设计,做好懒加载,避免一次性加载过多资源,浪费内存;

    3. 避免内存泄漏

      • 编码规范
        • 资源对象用完一定要关闭,最好加finally
        • 静态集合对象用完要清理
        • 接收器、监听器使用时候注册和取消成对出现
        • Context 使用注意生命周期,长生命周期引用直接用 ApplicationContext
        • 使用静态内部类,避免匿名内部类和非静态内部类,弱引用外部 Context 对象,确保对象可以被正确回收
      • 建设内存监控体系
        • 线下监控
          1. 使用 ArtHook 检测图片尺寸是否超出 imageview 自身宽高的2倍
          2. 编码阶段 Memery Profile 看 app 的内存使用情况,是否存在内存抖动,内存泄漏,结合 Mat 分析内存泄漏
        • 线上监控
          1. 上报app使用期间待机内存、重点模块内存、OOM率
          2. 上报整体及重点模块的 GC 次数,GC时间
          3. 使用 LeakCannery 自动化内存泄漏分析
    4. 兜底策略

      在低内存状态回调,根据不同的内存等级主动做一些事情

      比如在最严重的等级清空所有的bitmap,关掉所有界面,直接强制把app跳转到主界面,相当于app重新启动了一次一样,这样就避免了系统Kill应用进程,与其让系统 kill 进程抛异常,还不如浪费一些用户体验,自己主动回收内存。

    相关文章

      网友评论

          本文标题:说说内存溢出?

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