Android Runtime(ART) GC 日志手册

前言

本文用于快速理解 Android ART 的 GC 日志:涵盖日志格式与字段释义、常见 GC Reason 与收集器说明。基于真实日志的"示例与解读"一一对应解析,帮助在性能与内存问题排查中更快定位问题与优化方向。

GC日志何时会打印

  • 仅当被认为是"慢 GC"时才打印:
    • 暂停时间 > 5ms,或
    • GC 总时长 > 100ms。

日志格式

xml 复制代码
I/art: <GC_Reason> <GC_Name> <Objects_freed>(<Size_freed>) AllocSpace Objects,
<Large_objects_freed>(<Large_object_size_freed>) <Heap_stats> LOS objects, <Pause_time(s)>

字段快速对照:

  • <GC_Reason>:触发原因
  • <GC_Name>:收集器名称
  • <Objects_freed>(<Size_freed>):释放对象数/字节(非大对象空间)
  • <Large_objects_freed>(<Large_object_size_freed>):释放大对象数/字节(LOS)
  • <Heap_stats>:堆统计(空闲百分比,已用/总)
  • <Pause_time(s)>:暂停时间(以及总时长)

字段释义

  • Objects_freed:从非大对象空间回收的对象数。
  • Size_freed:从非大对象空间回收的字节数。
  • Large_objects_freed:从大对象空间回收的对象数。
  • Large_object_size_freed:从大对象空间回收的字节数。
  • Heap_stats:堆空闲百分比(已用/总)。
  • Pause_time:暂停与 GC 期间引用变更的对象数正相关。ART 的 CMS 在结尾附近有一次短暂停;移动 GC 在多数阶段有较长停顿。

触发原因(GC Reason)

  1. Concurrent:并发 GC;后台执行,不挂起应用线程,也不阻止分配。
  2. Alloc:堆满时分配触发;回收在发起分配的线程中执行。
  3. Explicit:显式调用(如 System.gc());不建议,可能阻塞分配并造成卡顿。
  4. NativeAlloc:Native 内存压力(如 Bitmap、RenderScript)触发。
  5. CollectorTransition:收集器/堆过渡,常见于低内存设备的进程状态切换(暂停可感知 ↔ 非暂停可感知)。
  6. HomogeneousSpaceCompact:齐性空间压缩,整理碎片、降低内存占用(多见于进入暂停可感知状态)。
  7. DisableMovingGc:非真实原因;表示移动收集器被阻塞(如 GetPrimitiveArrayCritical),强烈不建议使用。
  8. HeapTrim:非真实原因;表示 GC 被阻塞直至堆整理完成。

收集器名称(GC Name)

  1. Concurrent copying (CC):ART 现代默认收集器,并发复制,暂停低;LOS(大对象空间)单独处理。
  2. Young concurrent copying:仅回收年轻代,频率高、暂停更低,适合短生命周期对象抖动场景。
  3. Concurrent mark sweep (CMS):完整堆标记-清除,非移动;在部分版本或过渡阶段仍可见。
  4. Concurrent partial mark sweep:不处理图片空间与 zygote 空间。
  5. Concurrent sticky mark sweep:仅回收自上次 GC 后新产生的垃圾,代价更低。
  6. Marksweep + semispace:非并发复制/压缩,用于堆过渡与碎片整理等场景。

示例与解读

示例 1:

scss 复制代码
NativeAlloc concurrent copying GC freed 123645(7486KB) AllocSpace objects, 69(3248KB) LOS objects, 35% free, 44MB/68MB, paused 332us total 256.582ms

解读:

  • 触发原因:NativeAlloc(Native 内存压力,如 Bitmap/DirectByteBuffer/JNI)。
  • 收集器:concurrent copying
  • 释放:123645 (7486KB);大对象 69 (3248KB)
  • 堆统计:空闲 35%,已用 44MB / 总 68MB
  • 时延:暂停 332us;总时长 256.582ms(慢 GC)。
  • 关注点:排查图片/渲染/DirectBuffer 分配与复用,核对释放与生命周期。

示例 2:

scss 复制代码
Background concurrent copying GC freed 191217(10MB) AllocSpace objects, 91(22MB) LOS objects, 40% free, 35MB/59MB, paused 527us total 160.132ms

解读:

  • 触发原因:Background(后台阶段的并发回收)。
  • 收集器:concurrent copying
  • 释放:191217 (10MB);大对象 91 (22MB)
  • 堆统计:空闲 40%,已用 35MB / 总 59MB
  • 时延:暂停 527us;总时长 160.132ms(慢 GC)。
  • 关注点:后台批量回收幅度大,观察进入后台后的内存回落是否充分。

示例 3:

scss 复制代码
Background young concurrent copying GC freed 343568(21MB) AllocSpace objects, 23(696KB) LOS objects, 36% free, 34MB/55MB, paused 145us total 159.337ms

解读:

  • 触发原因:Background young(后台的 young 区回收,短生命周期对象较多)。
  • 收集器:concurrent copying
  • 释放:343568 (21MB);大对象 23 (696KB)
  • 堆统计:空闲 36%,已用 34MB / 总 55MB
  • 时延:暂停 145us;总时长 159.337ms(慢 GC)。
  • 关注点:对象抖动明显,检查热点分配路径与缓存/池化策略。

示例 4:

scss 复制代码
Explicit concurrent copying GC freed 300633(16MB) AllocSpace objects, 31(3616KB) LOS objects, 43% free, 31MB/55MB, paused 218us total 226.144ms

解读:

  • 触发原因:Explicit(显式调用,如 System.gc())。
  • 收集器:concurrent copying
  • 释放:300633 (16MB);大对象 31 (3616KB)
  • 堆统计:空闲 43%,已用 31MB / 总 55MB
  • 时延:暂停 218us;总时长 226.144ms(慢 GC)。
  • 关注点:避免在关键路径显式 GC;移除不必要的 System.gc()

常见告警信号

  • 当 Logcat 出现大量 GC 日志时,优先关注堆统计(如 31MB/55MB)。若已用/总内存比例长期走高且迟迟不回落,极可能存在内存泄漏。
  • 若 GC Reason 频繁为 Alloc,说明堆空间已逼近上限,短期内极易触发 OOM,应立即排查大对象与异常分配峰值。
相关推荐
袁美丽..4 小时前
Android --- SystemUI 导入Android Studio及debug
android·ide·android studio
袁美丽..4 小时前
Android studio的adb和终端的adb互相抢占端口
android·adb·android studio
鹏多多.5 小时前
flutter-使用fluttertoast制作丰富的高颜值toast
android·前端·flutter·ios
守城小轩5 小时前
Firefox Android 开发环境搭建全流程(四)
android·firefox·chrome devtools·指纹浏览器·浏览器开发
袁美丽..5 小时前
Android --- AOSP源码导入Android Studio
android·android studio
LiuYaoheng6 小时前
【Android】View 的基础知识
android·java·笔记·学习
出海小纸条6 小时前
Google Play 应用被拒-数据安全表单无效(设备上的应用)
android
和煦的春风6 小时前
简单讨论下lmkd 查杀机制
android
Android轮子哥6 小时前
月下载 40 万次的框架是怎么练成的
android