移动端测试===Android内存泄露和GC机制(转)
本文转自:https://www.testwo.com/article/1153
1、前言
Hello,小伙伴们,相信大家在项目测试中都遇到过内存泄露问题,小编也着实爬过很多坑。比如小编所测项目,更换了多实例版本的sdk,横竖屏切换后有MapView没有销毁,导致内存泄露。小编测试手表项目,因为手表内存有限,测试中常遇到应用无响应或者闪退,故而小编对GC机制进行了进一步学习了解。
本文先对Android内存垃圾回收机制进行介绍,之后对分析、定位内存泄露常用的测试方法进行总结,分享给大家。
2、Android内存垃圾回收(GC机制)
2.1综述
Android 应用中默认有三个线程:“main”主线程、GC线程、和Heap线程,而且在GC线程运行的过程中,主线程会中断执行。Java程序与C/C++等原生程序的一个不同点就是,Java虚拟机在运行Java程序的过程中,可以自动回收不再使用的对象实例,从而避免了程序员人工管理内存的繁琐工作。如果设备是单核CPU设备,一次只能运行一个线程,因此在GC线程运行的时候,必须中断主线程。但是如果设备上有多核CPU,即主线程可以和GC线程同时运行,在这种情况下执行GC,会不会中断主线程呢?答案是会的。
虽然有不同的内存垃圾回收实现算法,但有些算法需要中断其他Java线程的执行,如果中断的时间过长,给用户的感觉就是应用的响应速度变的越来越慢,甚至有可能出现ANR错误。
2.2Android内存管理原理
2.2.1垃圾内存回收算法
常见的垃圾回收算法引用计数法、标注并清理、拷贝、逐代回收,其中android系统采用的是标注并清理和拷贝GC,并不是大多数JVM实现中采用的逐代回收算法。在很多垃圾回收实现中,常常可以看到将几种算法合并使用的场景。
2.2.2Logcat中的GC信息
Logcat中GC输出的信息格式如下:
Dalvik虚拟机的Log信息
在Davlik虚拟机(非ART)中,每一次垃圾回收都会返回一条类似的信息。例子如下:
D/dalvikvm( 9050): GC_CONCURRENT freed2049K, 65% free 3571K/9991K, external 4703K/5261K, paused 2ms+2ms
它们大致可以分成如下几个部分:
D/dalvikvm: <GC_Reason> <Amount_freed>, <Heap_stats>, <External_memory_stats>, <Pause_time>
[GC的原因][回收的内存总量][GC堆内存的统计信息][外部内存的统计信息][中断时间]
各个字段的含义如下:
(1)、GC的原因,也就是GC类别,可分为:
GC_FOR_MALLOC 表示内存垃圾回收过程是因为在分配内存空间如(创建对象)时,内存不够而引发的。系统会杀死应用的进程并且回收所有内存。
GC_CONCURRENT 表明GC是在内存使用率达到一定的警戒线时,自动触发的。
GC_EXPLICIT 表明GC是被显式请求触发的。
GC_EXTERNAL_ALLOC在API版本10(Android3.0)以下的时候的垃圾回收机制。3.0以上版本所有的内存都在Dalvik堆中分配。它是用来回收dalvik虚拟机以外的内存(例如Bitmap中的内存或者NIObuffer中的内存)。
GC_HPROF_DUMP_HEAP 当请求生成HPROF文件来分析内存的时候会触发此类垃圾回收
(2)、回收的内存总量
(3)、回收后GC内存对的统计信息
堆中可用空间所占的百分比和(堆中对象的数量)/(堆的大小)
(4)、外部内存的统计信息
系统API版本10以下的系统中,Dalvik虚拟机堆外(分配的内存)/(限制的内存量)
(5)、GC造成的应用其他线程中断的时间
Concurrent类型的垃圾回收有两次暂停时间:一次发生在开始,另一次发生在结束。堆的内容越多,暂停的时间越长。
观察这些Log信息,如果heapstats中的数值(堆中对象数量)/(堆的大小)越来越大,那么应用中很有可能存在内存泄漏。
(6)、总结
一般根据下面两个线索判断应用是否存在内存泄露问题
1、应用运行一段时间后,因为内部抛出java.lang.OutOfMemoryError异常而崩溃;
2、在logcat中看到频繁的GC信息;
3、内存泄露
3.1什么是内存泄漏
对于不同的语言平台来说,进行标记回收内存的算法是不一样的,像Android(Java)则采用GC-Root的标记回收算法。下图(Google 2011的IO大会)展示了Android内存的回收管理策略。
图中的每个圆节点代表对象的内存资源,箭头代表可达路径。当圆节点与GC Roots存在可达路径时,表示当前资源正被引用,虚拟机是无法对其进行回收的(如图中的黄色节点)。反过来,如果圆节点与GC Roots不存在可达路径,则意味着这块对象的内存资源不再被程序引用,系统虚拟机可以在GC过程中将其回收掉。
有了上面的内存回收的栗子,那么接下来就可以说说什么是内存泄漏了。
从定义上讲,Android(Java)平台的内存泄漏是指没有用的对象资源任与GC-Root保持可达路径,导致系统无法进行回收。举一个最简单的栗子,我们在Activity的onCreate函数中注册一个广播接收者,但是在onDestory函数中并没有执行反注册,当Activity被finish掉时,Activity对象已经走完了自身的生命周期,应该被资源回收释放掉,但由于没有反注册,此时Activity和GC-Root间仍然有可达路径存在,导致Activity虽然被销毁,但是所占用的内存资源却无法被回收掉。
3.2泄漏的源头
这里,将其归位以下三类:
(1). 自身编码引起
由项目开发人员自身的编码造成。
(2). 第三方代码引起
这里的第三方代码包含两类:第三方非开源的SDK和开源的第三方框架。
(3). 系统原因
由Android系统自身造成的泄漏,如像WebView、InputMethodManager等引起的问题,还有某些第三方ROM存在的问题。
3.3泄漏的定位
内存泄漏不像闪退的BUG,排查起来相对要比较困难些,比较极端的情况是当应用OOM了才发现存在内存泄漏问题,对用户影响太大。为此,我们希望在测试过程中能够尽早发现问题。下面介绍几种分析内存泄露问题的工具、方法。
3.3.1静态代码分析工具 —— Lint
Lint是 Android Studio自带的工具,使用姿势很简单Analyze -> Inspect Code然后选择想要扫面的区域即可。
对可能引起泄漏的编码,Lint都会进行温馨提示。
关于Lint,大家可以自行拓展学习。
3.3.2Android Memory Monitor
Android Studio提供的工具,用于监控应用的内存使用状态,在开发中也是非常实用的工具,可以用来打印出内存的状态信息。
打印获得的内存信息如下,可以通过右上角的绿色三角形按钮去分析泄漏的Activity和一些重复的字符串,目前只支持这两个,希望Google后面能够加入更多可选分析规则。
3.3.3adb shell 命令
使用 adb shell dumpsys meminfo [PackageName],可以打印出指定包名的应用内存信息。
使用该命令可以很直观的观察到Activity的泄漏问题,是平常分析比较常用的一种方式。除了使用命令外,Android Studio也提供了下面的功能,和使用命令是一样效果的。
以上就是我在做内存泄漏定位分析的时候会用到的工具和方法,通常都是结合起来用,使用多个工具互补分析问题可以提高我们的效率和最终取得的效果。
以上,就是小编做内存泄漏分析的一些心得总结,如有错误和不足,还请大家指出。如果大家针对内存泄露测试、分析,还有什么建议或者心得,欢迎留言、一起探讨~~O(∩_∩)O~~
移动端测试===Android内存泄露和GC机制(转)的更多相关文章
- 移动端测试===Android内存管理: 理解App的PSS
Android内存管理: 理解App的PSS 原文链接:http://www.littleeye.co/blog/2013/06/11/android-memory-management-unders ...
- (转)专项:Android 内存泄露实践分析
今天看到一篇关于Android 内存泄露实践分析的文章,感觉不错,讲的还算详细,mark到这里. 原文发表于:Testerhome: 作者:ycwdaaaa ; 原文链接:https://teste ...
- Java 内存区域和GC机制分析
目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection, ...
- 【转载】Java系列笔记(3) - Java 内存区域和GC机制
Java系列笔记(3) - Java 内存区域和GC机制 转载:原文地址http://www.cnblogs.com/zhguang/p/3257367.html 目录 Java垃圾回收概况 Java ...
- Java 内存区域和GC机制-java概念理解
推荐几篇关于java内存介绍的文章 Java 内存区域和GC机制 http://www.cnblogs.com/hnrainll/archive/2013/11/06/3410042.html ...
- Java内存区域和GC机制篇
Java内存区域和GC机制一.目录 1.Java垃圾回收概括 2.Java内存区域 3.Java对象的访问方式 4.Java内存访问机制 5.Java GC 机制 6.Java垃圾收集器 二.Java ...
- Android内存泄露测试
Android性能测试过程中的一些常用命令: CPU: adb shell top -n | grep "+PackageName 内存: adb shell dumpsys meminfo ...
- Android 内存泄露测试数据处理--procrank,setprop,getprop(转)
1.Android内存测试常用的几个概念. VSS--virtual set size 虚拟耗用内存(包含共享库占用的内存)RSS--Resident set size实际使用的物理内存(包含共享库占 ...
- android 内存泄露测试
Android 程序由java语言编写,android的内存管理与java相似,通过new为对象分配内存,所有对象在java堆内分配空间,对象回收有个垃圾回收器来完成.GC就是垃圾收集的意思(Gaba ...
随机推荐
- ajax 请求 后台返回的文件流
download(url) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); // 也可以使用POST方式,根据接口 xhr. ...
- opencv 和 parfor
一次遇到两个不熟悉的,因此在一起记一下. OpenCV的全称是:Open Source Computer Vision Library. OpenCv是一个基于(开源)发行的跨平台计算机视觉库,可以运 ...
- 【bzoj3529】[Sdoi2014]数表 莫比乌斯反演+离线+树状数组
题目描述 有一张n×m的数表,其第i行第j列(1 <= i <= n ,1 <= j <= m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. ...
- Python 源码剖析(一)【python对象】
处于研究python内存释放问题,在阅读部分python源码,顺便记录下所得.(基于<python源码剖析>(v2.4.1)与 python源码(v2.7.6)) 先列下总结: ...
- SocketServer-实现并发处理2
转发自MnCu的博客: http://www.cnblogs.com/MnCu8261/p/5546823.html python基础之socket与socketserver ---引入 Socket ...
- POJ3261:Milk Patterns——题解
http://poj.org/problem?id=3261 给一个序列,求至少出现 k 次的最长重复子串,这 k 个子串可以重叠. 论文题+傻逼题. 上一道题(POJ1743)会做即可. 还是二分长 ...
- 洛谷 P4964 绫小路的特别考试 解题报告
P4964 绫小路的特别考试 题目背景 这世界上「胜利」便是一切.无关乎过程. 要付出多少牺牲都无所谓.只要最后我「胜出」那就行了. 题目描述 一场新的特别考试来临了,这次的考试内容是(wan e d ...
- 洛谷 P1291 [SHOI2002]百事世界杯之旅 解题报告
P1291 [SHOI2002]百事世界杯之旅 题目描述 "--在2002年6月之前购买的百事任何饮料的瓶盖上都会有一个百事球星的名字.只要凑齐所有百事球星的名字,就可参加百事世界杯之旅的抽 ...
- ContestHunter暑假欢乐赛 SRM 03
你们也没人提醒我有atcoderQAQ... A题曼哈顿距离=欧拉距离就是在同一行或者同一列,记录下i,j出现过的次数,减去就行,直接map过. B题一开始拿衣服了,一直以为排序和不排序答案是一个样的 ...
- mysql 读写分离,主从同步 理论
mysql主从复制中:第一步:master记录二进制日志.在每个事务更新数据完成之前,master在二进制日志记录这些改变.MySQL将事务写入二进制日志,即使事务中的语句都是交叉执行的.在事件写入二 ...