写在前面

英文原版链接,若是觉得本文哪里不好还请指出,以便及时修改,以下是译文

安卓是为移动设备设计的,所以开发者应该时刻留意app占用的RAM(Random-Access Memory)。尽管Dalvik和ART会例行垃圾回收(GC),但并不代表开发者可以忽略app的内存使用情况(什么时候在哪里分配/释放了多少内存)。为了确保稳定的用户体验,让系统能够在多个app之间迅速切换,app不要在用户没有和它交互时消耗不必要的内存,这一点很重要

P.S.Dalvik(Android专用的JVM)、ART(Android Runtime),Android4.4引入了ART,之前是Dalvik

即便在开发期间遵循所有的最佳实践来管理app的内存(开发者理应这样做),也可能会出现对象泄漏或者其它内存bug。唯一可靠的,能尽量减少app内存占用的方法就是用工具分析app的内存使用情况,本篇指南将详细说明应该怎么做

Log信息解释

查看app内存使用情况最简单的方式是运行时的log信息,GC执行后,会输出一段信息到logcat。logcat的输出可以在Device Monitor里查看,或者直接在IDE比如Android Studio里查看

Dalvik Log信息

在Dalvik(不是ART)模式下,每次FC会在logcat输出如下信息:

D/dalvikvm: , , ,

例如:

D/dalvikvm( 9050): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K, external 4703K/5261K, paused 2ms+2ms

GC Reason

什么触发了GC,以及属于哪种类型的垃圾回收,可能出现的值包括:

GC_CONCURRENT

heap快满了引起的并发GC

GC_FOR_MALLOC

heap已经满了,此时app尝试分配内存,所以系统只好阻止app并回收内存,导致内存分配失败

GC_HPROF_DUMP_HEAP

请求创建一个用来分析heap的HPROF文件,引发GC

P.S.hprof文件描述了heap使用情况,类似于Chrome的heapsnapshot文件

GC_EXPLICIT

显式GC,例如调用gc()(这种方式应该避免,要相信GC会在需要的时候自动执行)

GC_EXTERNAL_ALLOC

外部内存分配(比如像素数据存储在native memory里或者NIO byte buffer)引起的GC,只会在API 10和更低版本中出现(新一点的版本所有东西都在Dalvik heap里分配)

Amount freed

本次GC回收的内存大小

Heap stats

heap中可用内存所占百分比,以及[已使用内存大小]/[heap总大小]

External memory stats

外部内存统计数据,

在API 10和更低版本中,外部分配的内存,以及[已分配内存大小]/[GC下限]

P.S.达到GC下限时进行GC

Pause time

heap越大,需要的停顿次数越多,并发GC(GC Reason为GC_CONCURRENT)的停顿次数分2部分:第一部分是GC开始时,另一部分是GC结束时

记下这些log信息,关注heap stats(例子中是3571K/9991K),如果持续增长,可能就存在内存泄漏了

ART Log信息

与Dalvik不同,ART不会log非显式(隐式)请求的GC,GC只会在被判定为很慢时输出信息。更准确地,条件是GC停顿超过5ms,或者GC耗时超过100ms。如果app不是处于一种可察觉的停顿状态,那么GC不会就被判定为很慢,而显式GC会被log出来

ART的GC log中包含了以下信息:

I/art: () AllocSpace Objects, () LOS objects,

例如:

I/art : Explicit concurrent mark sweep GC freed 104710(7MB) AllocSpace objects, 21(416KB) LOS objects, 33% free, 25MB/38MB, paused 1.230ms total 67.216ms

GC Reason

什么触发了GC,以及属于哪种类型的垃圾回收,可能出现的值包括:

Concurrent

并发GC,不会挂起app线程,这种GC在后台线程中运行,不会阻止内存分配

Alloc

GC被初始化,app在heap已满的时候请求分配内存,此时,GC会在当前线程(请求分配内存的线程)执行

Explicit

GC被app显式请求,例如,通过调用System.gc()或者runtime.gc()。和Dalvik一样,ART建议相信GC,尽可能地避免请求显式GC。不建议使用显式GC,因为会阻塞当前线程,并引起不必要的CPU周期。如果GC导致其它线程被抢占的话,显式GC还会引发jank

P.S.jank是指第n帧绘制过后,本该绘制第n+1帧,但因为CPU被抢占,数据没有准备好,只好再显示一次第n帧,下一次绘制时显示第n+1帧

NativeAlloc

来自native分配的native memory压力引起的GC,比如Bitmap或者RenderScript对象

CollectorTransition

heap变迁引起的GC,运行时动态切换GC造成的,垃圾回收器变迁过程包括从free-list backed space复制所有对象到bump pointer space(反之亦然)。当前垃圾回收器过渡只会在低RAM设备的app改变运行状态时发生,比如从可察觉的停顿态到非可察觉的停顿态(反之亦然)

HomogeneousSpaceCompact

Homogeneous space compaction是free-list space与free-list space的合并,经常在app变成不可察觉的停顿态时发生,这样做的主要原因是减少RAM占用并整理heap碎片

DisableMovingGc

不是一个真正的GC原因,正在整理碎片的GC被GetPrimitiveArrayCritical阻塞,一般来说,因为GetPrimitiveArrayCritical会限制垃圾回收器过渡,强烈建议不要使用

HeapTrim

不是一个真正的GC原因,但GC被阻塞,直到heap trim结束

GC Name

ART有几种不同的GC

Concurrent mark sweep (CMS)

全堆垃圾收集器,负责收集释放除image外的所有空间

Concurrent partial mark sweep

差不多是全堆垃圾收集器,负责收集除image和zygote外的所有空间

Concurrent sticky mark sweep

分代垃圾收集器,只负责释放从上次GC到现在分配的对象,该GC比全堆和部分标记清除(mark sweep)执行得更频繁,因为它更快而且停顿更短

Marksweep + semispace

非并发的,复制堆过渡和homogeneous space compaction(用来整理heap碎片)使用的GC

Objects freed

本次GC从非大对象空间(non large object space)回收的对象数目

Size freed

本次GC从非大对象空间回收的字节数

Large objects freed

本次GC从大对象空间里回收的对象数目

Large object size freed

本次GC从大对象空间里回收的字节数

Heap stats

可用空间所占的百分比和[已使用内存大小]/[heap总大小]

Pause times

一般情况下,GC运行时,停顿次数和被修改的对象引用数成比例。目前,ART CMS GC只会在GC结束的时停顿一次,GC过渡会有一个长停顿,是GC时耗的主要因素

如果在logcat看到一堆GC信息,找到heap stats(例子中是25MB/38MB),如果持续增长从不减小,就可能存在内存泄漏。如果看到GC的原因是Alloc,那么说明heap已经要满了,快OOM了

gc android,Android GC Log解读相关推荐

  1. Android ART GC之GrowForUtilization的分析

    Android运行过程中有多种情况会触发垃圾回收(GC,garbage collection),以android 5.0为例,可以发现,在应用运行过程中最常见的触发GC的方式如下图所示: 此图是通过a ...

  2. Android 系统优化(33)---Android ART GC之GrowForUtilization的分析

    Android ART GC之GrowForUtilization的分析 转载请注明来自 https://hello2mao.github.io Android运行过程中有多种情况会触发垃圾回收(GC ...

  3. Android中GC的触发时机和条件

    本文分析基于Android R(11)源码 Java对象的创建由Allocator负责,回收由Collector负责.从Android O开始,对于前台应用默认的GC Collector是CC(Con ...

  4. Android dalvik GC相关的属性详解

    在dalvik中,GC的类型有三种: 1.GC_EXPLICIT: 应用主动调用System.gc()产生的GC事件. 2.GC_FOR_ALLOC: 内存分配时,发现可用内存不够时触发的GC事件. ...

  5. android gc分析,android GC浅析

    在dalvik中,GC的类型有三种: 1.GC_EXPLICIT: 应用主动调用System.gc()产生的GC事件. 2.GC_FOR_ALLOC: 3.GC_CONCURRENT: 给Java层的 ...

  6. Android BLE蓝牙详细解读

    代码地址如下: http://www.demodashi.com/demo/15062.html 随着物联网时代的到来,越来越多的智能硬件设备开始流行起来,比如智能手环.心率检测仪.以及各式各样的智能 ...

  7. android蓝牙设置特征属性,Android BLE蓝牙详细解读(二)

    上篇文章主要介绍了关于BLE的一些基础操作,我们能够大概了解到蓝牙操作的一些流程,上文末介绍了本人的一个BLE开源库,支持蓝牙一对多的连接方式,该库封装了蓝牙的开启.扫描.连接.断开.连接超时...一 ...

  8. Android中对Log日志文件的分析

    Android中对Log日志文件的分析 如何分析和研究Log文件 ,如何看日志信息 Log 在android中的地位非常重要,要是作为一个android程序员不能过分析log这关,算是android没 ...

  9. android jni打印log信息

    今天,讲讲在jni中如何打印logxx,用来进行调试. 一.实现 1.修改Android.mk文件. 在这个配置文件中我们加入如下一行代码: LOCAL_LDLIBS += -llog 注意:这行代码 ...

最新文章

  1. 字节跳动花50亿买了个什么?
  2. BZOJ 4221 [JOI2012春季合宿]Kangaroo (DP)
  3. python获取中文字体点阵坐标_点阵汉字显示 - freecamel的个人空间 - OSCHINA - 中文开源技术交流社区...
  4. Android游戏开发中绘制游戏触摸轨迹的曲线图
  5. 已知三个用不同数制表示的整数_数制的概念与常用的数制之间的转换。大学生必看!...
  6. 献给开发者的大礼--打造CSDN论坛专用阅读器(电脑报2006年11月6日 第44期)
  7. iOS与Opencv的探秘之Opencv认识,适配Xcode
  8. iPhone设备分辨率及尺寸
  9. UILocalNotification本地通知
  10. 【kafka】kafka 消费报错 No entry found for connection
  11. 【django小练习之主机管理界面】
  12. 在iOS端使用AVSampleBufferDisplayLayer进行视频渲染
  13. a number of 和the number of用法
  14. smartDNS让你的网络一触即达
  15. php实现 令牌桶,php 基于redis使用令牌桶算法实现流量控制
  16. MAC读取NTFS移动硬盘方法
  17. 配置错误 访问被拒绝 解决方案
  18. 利用comtypes.client批处理dwg文件(AutoCAD二次开发Python)
  19. 产品| 产品经理学习路径及职业规划
  20. bp神经网络原理 实现过程,BP神经网络的实现包括

热门文章

  1. neo4j的查询语法Cypher+python演示
  2. python网络爬虫系列教程——Python+PhantomJS +Selenium组合应用
  3. jquery系列教程3-DOM操作全解
  4. 用Mask-RCNN训练自定义大小的数据集
  5. 腾讯云配置Ubuntu使用SSH登录
  6. IIS上部署网站问题总结
  7. 一个故事理解什么是接口回调
  8. Android开发技术周报 Issue#101
  9. ajax data参数
  10. pcie inbound、outbound及EP、RC间的互相訪问