热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

AndroidApp内存泄露测试方法总结

和你一起终身学习,这里是程序员Android经典好文推荐,通过阅读本文,您将收获以下知识点:一、内存泄露二、A

和你一起终身学习,这里是程序员 Android

经典好文推荐,通过阅读本文,您将收获以下知识点:

一、内存泄露
二、 Android的GC机制
三、为什么会内存泄露
四、 系统级别的内存管理
五、内存抖动
六、内存名词VSS、RSS、PSS、USS解释
七、 内存值获取方法
八、 测试场景选择
九、 定位内存泄露的原因(

一、内存泄露

Android系统为每一个运行的程序都指定了一个最大运行内存,超过这个值则会触发OOM机制,反应在界面就是闪退、 Crash现象,导致OOM发生的原因比如内存泄露或者是代码不考虑后果使用大量的资源,都有可能导致OOM出现的。OOM的临界值可以通过adb shell getprop | findstr “heap”查看到:

Android App内存泄露测试方法总结
image.png

二、 Android的GC机制

Android GC机制沿用了java的GC机制,当需要新内存去分配对象的时候而剩余不够的时候,会触发GC,把无用的对象回收掉,其中一个重要的算法便是分代式算法,这个算法把虚拟机分为年轻代、老年代和持久代,对象先分配到年轻代,然后GC多次后还存活的将会移动到老年代,老年代就不会频繁触发GC机制,一般触发频繁的都是年轻代的对象。

三、为什么会内存泄露

上面我们知道了GC机制,那么如果GC过后程序还是没有内存,那么会发生OOM,导致GC后还是没有足够内存分配新对象的主要原因就是内存泄露了。首先要知道内存泄露也就是GC不掉的根源是生命周期长的对象持有生命周期短的对象,导致无用的对象一直无法回收。以下是几个典型的分类:

1) 静态类相关的泄露:

static对象的生命周期伴随着整个程序的生命周期,所以这块要注意不要把一些对象引用添加到static对象里面去,会造成与之关联的对象无法回收。

2)各种资源的释放:

包括cursor的关闭,IO流的关闭,bitmap的回收等,进行一些带有缓存的资源一定要关闭或者释放。

3)Handler的泄露:

调用handler的delay的时候,会被认为对象是有用的,导致无法回收,还有handler开启线程去下载东西没有下载完成的时候,也会因为线程导致无法回收activity;或者使用handlerThread的时候,有延迟的方法,都会导致无法回收。其主要原因在于handler是持有activity的引用,主线程不是自带一个Looper然后给handler用,导致有关联关系。

4)各种注册引用方法:

比如一个常驻的后台线程处理某些时间,把当前对象注册,因为一直持有对象引用,导致这个activity一直保留,所以不用的时候需要反注册。

5)把对象缓存进容器内却忘记remove掉:

有时候为了加快页面响应,结果缓存一些对象到容器内,结果越加越多,然后挂掉。

四、 系统级别的内存管理

1)LMK机制和oom_adj的值

Android内核有个专用的驱动low-memory-kill,当系统级别的内存不够的时候会根据oom_adj的值以及内存分配状况去kill掉某个进程,oom_adj可以在/proc/[pid]/oom_adj看到,并且这个值会随着进程的状态改变而改变,比如系统进程一般是-16,越大越容易被干掉。

2)5个进程的优先级

前台进程:当前运行的,基本不死 ;

可见进程:界面可以见到,比如被遮挡 ;

服务进程:进程带后台服务的,比如播放器 ;

后台进程:点击home键,但不退出,就是后台进程了,有比较大几率会被杀;

空进程:退出应用程序,还在后台保留这空进程,为的是加快启动速率,最优先。

五、内存抖动

内存抖动是指内存频繁地分配和回收,而频繁的GC会导致卡顿,严重时还会导致OOM(主要原因还是有因为大量小的对象频繁创建,导致内存碎片,从而当需要分配内存时,虽然总体上还是有剩余内存可分配,而由于这些内存不连续,导致无法分配,系统直接就返回OOM了)

六、内存名词VSS、RSS、PSS、USS解释

VSS – Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)

RSS – Resident Set Size 实际使用物理内存(包含共享库占用的内存)

PSS – Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)

USS – Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)

大小规律:

一般来说内存占用大小有如下规律:VSS >= RSS >= PSS >= USS

Android App内存泄露测试方法总结
image.png

七、 内存值获取方法

使用命令 adb shell dumpsys meminfo package_name 获取内存信息,如日历的内存信息如下:

Android App内存泄露测试方法总结
image.png

PSS Total:进程各部分内存的消耗,是所有进程PSS相加得到系统占用内存的总和

Native Heap:Native代码分配的内存,虚拟机和Android框架分配内存。关于什么是Native代码,即非Java代码分配的内存

Dalvik Heap:Java对象分配的占据内存

Dalvik Other:类数据结构和索引占据内存

Stack:栈内存

Private Dirty:它基本上是进程内不能被分页到磁盘的内存,也不和其他进程共享,private Dirty内存是最重要的部分,因为只被自己进程使用

Private Clean:是已经映射持久文件使用的内存页(例如正在被执行的代码),因此一段时间不使用的话就可以置换出去

Heap Alloc:是Dalvik堆和本地堆分配使用的大小,它的值比Pss Total和Private Dirty大,因为进程是从Zygote中复制分裂出来的,包含了进程共享的分配部分

Ashmem:不以dalvik-开头的内存区域,匿名共享内存用来提供共享内存通过分配一个多个进程,Android匿名共享内存是基于Linux共享内存的,都是在tmpfs文件系统上新建文件,并将其映射到不同的进程空间,从而达到共享内存的目的,只是,Android在Linux的基础上进行了改造,并借助Binder+fd文件描述符实现了共享内存的传递。

Other dev:内部driver占用的内存

.so mmap:C 库代码占用的内存

.jar mmap:Java 文件代码占用的内存

.apk mmap:apk代码占用的内存

.ttf mmap:ttf 文件代码占用的内存

.dex mmap:Dex 文件代码占用的内存

Other mmap:其他文件占用的内存

八、 测试场景选择

内存出现泄漏的前提条件一定是有新的内存分配,所以测试场景会选择有新对象创建的场景,并结合用户的使用场景和频率来确定优先级。测试场景主要有以下三种情况,配合测试次数,然后可以每5次获取一次内存值进行判断,一般测试300次,如果各种内存测试完成并等待5分钟后内存没有释放,则高概率存在内存泄露:

1)新画面打开

由于新的画面打开,就会创建新的Activity和View,并有许多其他对象被创建。

测试方法:

反复进入退出需要测试的目标Activity,如果发现Activities和Views的一直在增长,则内存泄露一定发生(退出时如果手动GC,则Activities和Views的数量应该为0)

2)画面旋转

当屏幕旋转时,Orientation设置发生了改变,当前显示的Activity会被重新创建。

测试方法:进入需要测试的目标Activity,反复横竖屏切换,如果发现Activities数量等其他值一直在增长,则内存泄露一定发生

3)滑动屏幕

滑动屏幕会使屏幕中显示的对象(比如浏览器小说阅读内容)创建。

测试方法:进入需要测试的目标Activity,一直固定某个方向滑动(向左),如果发现内存值一直在增长,则内存泄露一定发生

Case例子,仅供参考:

Android App内存泄露测试方法总结
image.png

测试过程中的值记录模板,仅供参考:

Android App内存泄露测试方法总结
image.png

注意:

1)每个应用的脚本需要获取的信息可以直接涉及好关联应用或进程的数据值,例如测试camera时后台camera服务进程,多媒体进程、相册进程。

2)针对内存泄露的测试,需要开发自动化脚本测试,然后测试过程中获取测试的值存入execl的固定模板,测试完成后根据测试结果数据判断是否有内存泄露

九、 定位内存泄露的原因

如果是真机测试,安装一个debug版本的apk,否则monitor无法显示进程

方法一:使用DDMS(Monitor)检测内存泄露–需要

Android App内存泄露测试方法总结
image.png

步骤2、然后在打开DDMS, 选择Heap标签,然后点击Cause GC按钮,点击Cause GC是手动触发JAVA垃圾回收器,如下图:

Android App内存泄露测试方法总结
image.png

如果我们要测试某个Activity是否发生内存泄露,我们可以反复进入和退出这个Activity, 再手动触发几次垃圾回收,观察上图中 data object这一栏中的 Total Size的大小是保持稳定还是有明显的变大趋势,如果有明显的变大趋势就说明这个Activity存在内存泄露的问题,需要在具体分析。

参考链接:https://zhuanlan.zhihu.com/p/68351554

至此,本篇已结束。转载网络的文章,小编觉得很优秀,欢迎点击阅读原文,支持原创作者,如有侵权,恳请联系小编删除,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!


推荐阅读
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
author-avatar
PHP小龙
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有