android crash治理:
我的crash治理:
- 代码逻辑上的错误引发的crash-----修复并总结
- 兼容性问题导致的crash
- 内存导致的crash---内存问题可能引发卡顿、cpu增长、oom
遇到一些和系统相关的问题,要去查看对应版本的源码,从源码中查看可能出现问题的原因。
美团外卖总结
常规crash
NullPointerException 为初始化,或者在使用过程中未判空,多线程变量可见性受到影响。
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 数量超出限制
线程数量超出限制
虚拟内存不足
进程间内存分配

cpu和gpu使用同一个RAM
RAM 分为多个“页面”。通常,每个页面为 4KB 的内存。
系统会将页面视为“可用”或“已使用”。可用页面是未使用的 RAM。已使用的页面是系统当前正在使用的 RAM,并分为以下类别:
- 缓存页:有存储器中的文件(例如代码或内存映射文件)支持的内存。缓存内存有两种类型:
- 匿名页:没有存储器中的文件支持的内存(例如,由设置了
MAP_ANONYMOUS标记的mmap()进行分配)- 脏页:可由
kswapd移动到 zRAM/在 zRAM 中进行压缩以增加可用内存
- 脏页:可由
注意:干净页包含存在于存储器中的文件(或文件一部分)的精确副本。如果干净页不再包含文件的精确副本(例如,因应用操作所致),则会变成脏页。干净页可以删除,因为始终可以使用存储器中的数据重新生成它们;脏页则不能删除,否则数据将会丢失。
https://developer.android.google.cn/topic/performance/memory-management
内存管理方案·
系统层面
- kswapd机制 共享页,匿名页(脏页,干净页)
- LMK机制
- 配合框架自身的生命周期管理机制。
内存回调:
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);