美团技术文档总结-crash

android crash治理:

我的crash治理:

  1. 代码逻辑上的错误引发的crash-----修复并总结
  2. 兼容性问题导致的crash
  3. 内存导致的crash---内存问题可能引发卡顿、cpu增长、oom

遇到一些和系统相关的问题,要去查看对应版本的源码,从源码中查看可能出现问题的原因。

美团外卖总结

美团外卖Android Crash治理之路

常规crash
  1. NullPointerException 为初始化,或者在使用过程中未判空,多线程变量可见性受到影响。

  2. IndexOutOfBoundsException等

系统crash

一些厂商经过系统定制导致的问题,通过java hook 和native hook 的方式进行解决。
下面是常见的解决思路:

尝试找到造成Crash的可疑代码,看是否有特异的API或者调用方式不当导致的,尝试修改代码逻辑来进行规避。
通过Hook来解决,Hook分为Java Hook和Native Hook。Java Hook主要靠反射或者动态代理来更改相应API的行为,需要尝试找到可以Hook的点,一般Hook的点多为静态变量,同时需要注意Android不同版本的API,类名、方法名和成员变量名都可能不一样,所以要做好兼容工作;Native Hook原理上是用更改后方法把旧方法在内存地址上进行替换,需要考虑到Dalvik和ART的差异;相对来说Native Hook的兼容性更差一点,所以用Native Hook的时候需要配合降级策略。
如果通过前两种方式都无法解决的话,我们只能尝试反编译ROM,寻找解决的办法。

OOM

常见内存问题引发的oom

常见的 oom 问题一般分为

java 内存溢出
无连续可用空间
java.lang.OutOfMemoryError: Failed to allocate a 9224 byte allocation with 8384232 free bytes and 15MB until OOM; failed due to fragmentation (required continguous free 12288 bytes where largest contiguous free 8192 bytes)
FD 数量超出限制

线程数量超出限制

虚拟内存不足

进程间内存分配

image.png

cpu和gpu使用同一个RAM
RAM 分为多个“页面”。通常,每个页面为 4KB 的内存。

系统会将页面视为“可用”或“已使用”。可用页面是未使用的 RAM。已使用的页面是系统当前正在使用的 RAM,并分为以下类别:

  • 缓存页:有存储器中的文件(例如代码或内存映射文件)支持的内存。缓存内存有两种类型:
    • 私有页:由一个进程拥有且未共享
      • 干净页:存储器中未经修改的文件副本,可由 kswapd 删除以增加可用内存
      • 脏页:存储器中经过修改的文件副本;可由 kswapd 移动到 zRAM 或在 zRAM 中进行压缩以增加可用内存
    • 共享页:由多个进程使用
      • 干净页:存储器中未经修改的文件副本,可由 kswapd 删除以增加可用内存
      • 脏页:存储器中经过修改的文件副本;允许通过 kswapd 或者通过明确使用 msync()munmap() 将更改写回存储器中的文件,以增加可用空间
  • 匿名页:没有存储器中的文件支持的内存(例如,由设置了 MAP_ANONYMOUS 标记的 mmap() 进行分配)
    • 脏页:可由 kswapd 移动到 zRAM/在 zRAM 中进行压缩以增加可用内存

注意:干净页包含存在于存储器中的文件(或文件一部分)的精确副本。如果干净页不再包含文件的精确副本(例如,因应用操作所致),则会变成脏页。干净页可以删除,因为始终可以使用存储器中的数据重新生成它们;脏页则不能删除,否则数据将会丢失。

https://developer.android.google.cn/topic/performance/memory-management

内存管理方案·

系统层面

  1. kswapd机制 共享页,匿名页(脏页,干净页)
  2. LMK机制
  3. 配合框架自身的生命周期管理机制。
    内存回调:
    onTrimMemory,可以在 Application,Activiy,Service 和 ContentProvider 中重写接口方法来实现内存变化的监听ComponentCallbacks2
public interface ComponentCallbacks2 extends ComponentCallbacks {

    /** @hide */
    @IntDef(prefix = { "TRIM_MEMORY_" }, value = {
            TRIM_MEMORY_COMPLETE,
            TRIM_MEMORY_MODERATE,
            TRIM_MEMORY_BACKGROUND,
            TRIM_MEMORY_UI_HIDDEN,
            TRIM_MEMORY_RUNNING_CRITICAL,
            TRIM_MEMORY_RUNNING_LOW,
            TRIM_MEMORY_RUNNING_MODERATE,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface TrimMemoryLevel {}
    ..........
    void onTrimMemory(@TrimMemoryLevel int level);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容