type
status
date
slug
summary
tags
category
password
icon

什么是内存泄露?

  • 传统定义的内存泄露:申请的内存忘记释放了。
  • Android (或 JVM)的内存泄露:短⽣命周期的对象被⻓⽣命周期的对象持有,从⽽导致短⽣命周期的对象不能被释放

垃圾回收机制

垃圾回收机制分为「引⽤计数法」和「可达性分析法」:
  • 「引⽤计数法」 Python , Object-C , Swift ⽤⼀个计数器记录⼀个对象被引⽤的次数,如果引⽤的次数被减少到 0 那么说明这个对象是垃圾对象。 都是引⽤计数(引⽤计数有循环引⽤的问题)
  • 「可达性分析法」 Java Jvm 通过⼀些 GC Roots 向下搜索,如果可以被 Gc Roots 引⽤到的对象,说明这个对象不是垃圾对象,反之这个对象就算互相引⽤了也是垃圾对象 那些对象会被作为 GC Roots 呢?
    • 在线程栈中的局部变量,也就是正在被调⽤的⽅法,它⾥⾯的参数和局部变量
    • 存活的线程对象
    • JNI 的引⽤
    • Class 对象,因为 Android 加载 Class 后不会卸载 Class
    • 引⽤类型的静态变量

内存泄露的问题

内存泄漏并不会⻢上把程序搞挂掉。但是随着应⽤的使⽤,不能回收的垃圾对象会越来越多,就导致了可⽤的内存越来越少,到最后应⽤就有可能在任何位置抛出 OutOfMemoryError ,这种情况下,每次 OOM 错误堆栈都不同,就很难定位问题。

监控 Activity 和 Fragment 原理

通过注册 ApplicationActivity 上的⽣命周期回调来完成在 ActivityFragment 销毁的时候开始观察。
1.x 的 LeakCanary 只监控了 support 包和 API 26 以上的 Fragment 。

四⼤引⽤

  • 强⼀点的引⽤ 强引⽤——不会被垃圾回收
  • 弱⼀点的引⽤
    • 弱引⽤(WeakReference)——可以通过 get() 获得引⽤对象,会被垃圾回收
    • 软引⽤(SoftReference)——可以通过 get() 获得引⽤对象,内存不⾜会被垃圾回收
    • 虚引⽤(PhantomReference)——不能通过 get() 获得引⽤对象,会被垃圾回收
💡
在 Android 中,官方推荐使用 android.util.LruCache 来作为缓存,而不是使用软引用,软引用的效率比较低
弱引⽤引⽤对象被垃圾回收之前,如果引用对象只被弱引用引用那么这个对象一定会在垃圾回收时被回收),弱引用会将自己放⼊它关联的队列中。所以可以通过队列中是否有对应的引⽤来判断对象是否会被垃圾回收了。
notion image

⽅法 watch() 源码分析

原理:就是通过弱引⽤的⽅式来判断队列中是否有弱引⽤来判断对象是否被垃圾回收了。
首先生成一个引用队列,然后将怀疑的对象生成一个 key,通过 key 创建一个弱引用对象,当 GC 回收这个对象时,弱引用会把自己添加到引用队列,这样就可以通过引用队列中的 key,去排除怀疑对象,剩余的 key 就是 GC 无法回收的引起内存泄露的对象。
触发 GC 的正确姿势
通过 android.os.Debug.dumpHprofData() 来获取 hprof ⽂件
分析会在独⽴进程中进⾏, 1.x 内部使⽤ haha , 2.x 内部使⽤ shark 。 在 1.x 版本中,通过 haha 第三⽅库进⾏堆⽂件分析。 在 2.x 版本中,通过 shark 第三⽅库进⾏堆⽂件分析,内存占⽤⼤幅度减少,分析速度⼤幅度提⾼。

2.0 不需要主动初始化的原理

ContentProvider#onCreate 会在 Application#onCreate 之前先执⾏ ,在这个 onCreate 中就可以进⾏初始化了。 LeakCanary 2.0 利⽤了这个 原理,所以不需要我们⼿动进⾏初始化。
 
RecyclerView 原理解析泛型类型的创建
Loading...
shuouyang
shuouyang
android开发 ReactNative开发 小程序开发
最新发布
AOSP 环境搭建
2025-3-29
View 绘制流程-源码解析
2025-3-12
HTTP
2025-3-4
JVM 虚拟机
2025-2-28
蓝牙-BLE-基础
2025-2-28
从 OkHttp 的原理来看 HTTP
2025-2-19
公告
🎉热点信息🎉
--- 1 ---
Jet Brains 推出新的跨平台支持 Kotlin MultiPlatform
--- 2 ---
新的小巧便捷的依赖注入框架 Koin
--- 3 ---
新一代 API 查询语言 GraphQL