安卓内存分析

表头 含义 分析重点
Class Name 类名(对象的类型) 找你自己的业务类、Activity/Fragment、Bitmap、大数组等
Allocations 该类的对象实例数量 数量异常多 → 可能重复创建或泄漏(比如 Activity 应该只有 1 个却有 5 个)
Native Size 该类对象在Native 层(C/C++)占用的内存 图片、ByteBuffer、MediaCodec 等 Native 内存大户看这里
Shallow Size 对象自身占用的内存大小(不含它引用的对象) 看单个对象本身的开销(比如 byte \[\]、long \[\] 这种数组类)
Retained Size 对象自身 + 它能直接 / 间接引用到的所有对象的总内存 最关键指标:代表如果这个对象被 GC 回收,能释放多少内存

内存大户:

  1. byte[]

    • Allocations:89,643 个
    • Shallow Size:10,951,673 字节(约 10.4 MB)
    • Native Size:99,804,707 字节(约 95.2 MB)→ 说明你的 App 里有大量字节数组,且很多关联到 Native 内存(大概率是图片、音视频、网络 IO 缓存)
  2. DirectByteBuffer / DirectByteBuffer$MemoryRef

    • Allocations:33,740 + 22,500 个
    • Shallow Size:2,024,400 + 675,000 字节→ 大量直接内存缓冲区,常见于:
      • 网络请求(OkHttp/Retrofit)
      • 音视频编解码(MediaCodec)
      • 图片加载库(Glide/Picasso 用的 Native Buffer)
  3. MediaCodec$... 系列:

    • MediaCodec$BufferMap$CodecBufferMediaCodec$BufferInfo 数量都在 22k+→ 明显是音视频播放 / 录制 / 推流场景在占用内存,可能是 Codec 资源没及时释放

三、下一步具体分析步骤(按优先级)

步骤 1:先确认 "谁在占内存最多"
  1. 点击 Shallow SizeNative Size 列标题 ,按降序排序,锁定 Top 3~5 个大户(你这里已经是 byte[]StringDirectByteBuffer 等)
  2. 重点看:
    • 你自己的业务类(包名开头的类,比如 com.xxx.xxx
    • Activity/Fragment:数量是否超过预期(比如关闭页面后还残留多个实例)
    • Bitmap:如果存在,看 Shallow Size 和 Native Size(Bitmap 的 Native Size 就是图片像素内存)
步骤 2:深入分析 byte[] 这个最大户(核心操作)
  1. 双击 byte[] 这一行,展开它的实例列表
  2. 选中一个大尺寸的 byte \[\] 实例(按 Shallow Size 排序,找最大的几个)
  3. 右侧面板切换到 References (引用链),看:
    • 谁在引用这个 byte \[\]?
    • 是你的业务代码?还是第三方库(Glide、OkHttp、FFmpeg、MediaCodec 等)?
    • 引用路径里有没有 静态变量(static)、单例、长生命周期对象(比如 Application、Service) ?→ 如果是静态引用持有大 byte \[\],这就是典型的内存泄漏
步骤 3:分析 DirectByteBufferMediaCodec 相关对象
  1. 双击 DirectByteBuffer ,看实例的引用链:
    • 来源:OkHttp 的响应缓存?图片加载的 Native Buffer?还是音视频流 Buffer?
    • 数量是否随操作不断上涨(比如反复进入播放页面后数量翻倍)?
  2. MediaCodec 相关类:
    • 退出播放页面、停止推流后,这些对象数量是否下降?
    • 如果不下降 → 说明 Codec 资源、Surface、Buffer 没释放(比如没调用 release()stop()
步骤 4:判断是否存在内存泄漏
  1. 先点顶部的 垃圾桶图标(Force GC),触发垃圾回收
  2. 重新捕获一次堆转储(Dump Java Heap)
  3. 对比两次:
    • 如果 byte[]DirectByteBufferMediaCodec 相关对象数量几乎没减少 → 泄漏风险极高
    • 如果大幅减少 → 多半是临时缓存,属于正常波动
步骤 5:定位到具体代码行

当你在引用链里找到可疑对象后:

  • 右键引用链中的某一行 → 选择 Jump to Source(跳转到源码)
  • 直接定位到:
    • 哪个类、哪一行代码创建了这个大对象
    • 哪个地方持有了不该持有的引用(比如静态集合、单例)

四、针对你当前场景的针对性建议 💡

从你的堆转储看,明显偏向 Native/IO/ 音视频场景,建议重点排查:

  1. 图片加载
    • 是否用了 Glide/Picasso?有没有正确配置 skipMemoryCachediskCacheStrategy
    • 是否有超大图没做采样压缩(inSampleSize)?
  2. 音视频模块
    • 播放 / 录制结束后,是否完整调用了 MediaCodec.release()AudioTrack.release() 等?
    • 是否复用了 Codec 而没有正确释放旧实例?
  3. 网络 / IO 缓存
    • OkHttp 是否配置了过大的连接池 / 缓存?
    • 是否有读写大文件后没关闭流、没释放 Buffer?
相关推荐
flower_drop12 小时前
基于 WebUSB 与 CDP:在浏览器端实现 Android 设备通信与无证书抓包实践
android·chrome·测试工具·adb·bug·edge浏览器
撩得Android一次心动14 小时前
Jetpack Compose 知识点整理1【个人用】
android·学习·kotlin·android jetpack·compose
OpenAnolis小助手15 小时前
一句话看透 JVM,SysOM 诊断 Skill 新增 Java 应用诊断能力
java·开发语言·jvm·阿里云·操作系统控制台·sysom
ForteScarlet15 小时前
Kotlin 2.4.20 现已发布,新特性多不多?
android·java·开发语言·开源·kotlin·jetbrains
方白羽17 小时前
Android Studio 自动国际化插件:SmartI18n
android·android studio·intellij idea
小七在进步19 小时前
C++入门(2)
java·jvm·c++
码农coding20 小时前
android12 状态栏图标的加载流程
android
hai_android20 小时前
Kotlin 协程作用域源码剖析
android·kotlin
zuozong_21 小时前
内存的管理
jvm
Yeyu21 小时前
Android 画中画(PiP)小窗播放:怎么做、以及它到底是怎么工作的
android