Android性能优化-内存泄漏

1.如何去优化自己现有的项目,运行更加流畅
单个app进程 会根据手机性能分配不同的内容如: 8m 16m 32m 64m
2.当然最好的是在开发项目是就避免内存泄漏
在android应用层开发的时候,主要还是对java层的内存进行分析
( 而c 和c++,是自己去分配内存和释放内存 -- 手动管理 malloc free)
3.内存泄漏:内存不在掌控之内,当一个对象已经不需要使用了,本该回收时,而有另一个正在使用的对象持有它的引用,从而导致对象不能被回收而停留在堆内存中,这样就产生了内存泄漏。
4.java 中GC也会占用CPU性能而大量的分配内存和GC回收的话,就会造成GC抖动,一样会使应用变卡,所以,我们也一样要避免。
5.了解Java回收机制,对象不再有任何的引用的时候,才会被GC回收。
静态的:
在程序编译时就已经分配好,这块的内存在程序整个运行期间都一直存在
存放的是静态数据。全局的static数据和常量
栈式的
存放了编译器可知的各种基本数据类型,(boolean byte,char,short,int,float,long,double)对象的引用(reference引用指针),
在执行函数(方法)时,函数的一些内部变量
堆内存
存放的是对象实例,动态内存分配,java中直接依赖GC机制
StrongReference:
回收时机:从不回收,使用:对象一般保存,生命周期:JVM停止的时候才会终止
SoftReference :
回收时机:到内存不足的时候,使用:SoftReference<String>结合ReferenceQueue构造有效期短;生命周期:内存不足时终止
WeakReference:
回收时机:在垃圾回收的时候,使用:同软引用,生命周期:GC后终止
PhatomReference:
回收时机:在垃圾回收的时候,合ReferenceQueue来跟踪对象被垃圾回收期回收的活动;生命周期:GC后终止
开发时:为了防止内存溢出,处理一些比较占用内存大并且生命周期长的对象的时候,可以尽量使用软引用和弱引用。

1.使用Android Monitor:
可以看右边两个颜色块的说明:
Allocated :代表已被分配的
Free: 代表没有被使用的内存
在Memory 有个卡车的标志 Initiate GC,代表手动GC按钮,而一般检测一个activity是否有内存泄漏的时候,是先记录当前的内存分配情况,然后打开需要检测的activity,进行一系列操作后关闭后GC,再次记录对比之前记录的情况,如果内存大于之前的值,则代表有内存泄漏,分析代码。
Dump Java Heap
基本在点击这个按钮之前,我一般会先GC下,这样可以减少无用的对象,在点击这个按钮后,耐心等待一会,就会发现有生成一个hprof文件,由此记录对比分析。基本可以解决大部分的OOM。
Start Allocation Tracking
这个主要是对各个线程作分析,使用方法先点击一次然后进行想检测的操作,最后在点击一次结束,然后找到自己想检测的方法,可以查看对应的方法,分析内存情况。

当app退出的时候,这个进程里面所有的对象应该就都被回收了,尤其是很容易被泄露的(View,Activity)是否还内存当中。
可以让app退出以后,查看系统该进程里面的所有的View、Activity对象是否为0.
工具:使用AndroidStudio--AndroidMonitor--System Information--Memory Usage查看Objects里面的views和Activity的数量是否0.

2.MAT 使用Eclipse插件 Eclipse Memory Analyzer
首先在运行时,参照上面使用Android Monitor,找到点击Dump Java Heap生成的文件,可以点击右边的Captures,右键点击Export to standard .hprof 文件,然后使用 Eclipse Memory Analyzer工具点File选择 open Heap dump ,将对应的文件导入,选择 Leak Suspect Report ,自动检查这个dump堆可能泄露的地方,给出报告对象的存活和为什么他们还没有被垃圾回收器回收掉。

现在大概介绍下 Eclipse Memory Analyzer的几个模块
action模块下:
Histogram:柱状图,列举了每个class中对象的实例
Dominator Tree :支配树 列举了存活着的最大的对象
Top Consumers: 高级用户:圆形图打印最大的对象
Duplicate Classes:重复的类 检测由多个类装载器加载的类。

report 模块下:
Leak Suspect 泄漏怀疑 包含了可能泄漏的和系统的概况
Top Componments 顶部组件:组件的列表报告大于总堆的1%。

1.怀疑对象
1)步骤记录,首先打开记录的文件。然后下面任务栏中的Navigation中的点击histogram右键选择add to Compare Basket,记得将两个文件都添加都Compare Basket
切换到Compare Basket,就可以看到两个histogram,点击!就会出现Compared Tables ,这里就有两个对象个数的对比结果。然后具体对象的对比,还有就是Shallow Heap和对象占用内存的对比

2)MAT对比操作前后的hprof来定位内存泄漏,bar栏上找到Group by... 的一个按钮,上面有一个Group By package,输入自己的包名,这样就可以找到自己写的代码的对象个数及堆栈大小。

2.MAT分析hprof来定位内存泄漏原因所在。
1)Dump出内存泄漏当时的内存镜像hprof,分析怀疑的类
2)把上面得出的这些对象逐一排查,
(1)进入histogram,过滤出某一个嫌疑对象的类
(2)然后分析持有改类对象引用的外部对象(在该类上面点击List Object--->with incoming references )
(3)过滤其他引用 (在类上面点击右键Merge Shortest Paths to GC Roots--->exclude all phantom/weak/soft etc.references)
(4)逐个分析每个对象的GC路径是否正常,此时就要进入代码分析此时这个对象的引用持有是否合理。

总结,容易出现内存泄漏几种情况
单例传入Context
接口监听 getViewTreeObserver
InputMethodManager
多线程
停止动画
Handler

性能优化的工具:
Android monitor
Allaction Tracking: 追踪内存分配信息。可以很直观的看到某个操作的内存是如何进行分配
打开Android Device Monitor 找到Allaction Tracking ,点击StartTracking ,执行手机操作,点击GetAllocation
当然这个不打开Android Device Monitor使用android Monitor也是可以的,Android Monitor则是点击开始和结束,会自动生成一个.alloc文件。在左上角有点击group by Methon &allocator 在后面又有一个块状的圆形图就可以一个内存分配情况,当然也可以切换为柱状图,点击自己想要的块,然后就可以选取我们想要检查的类

LeakCanary 直接可以在手机端查看内存泄露的工具
具体使用方法就不在此做详细介绍了,在https://github.com/square/leakcanary 有比较详细的介绍,使用也十分的简单,只要在代码中做好那些配置,可以关注下运行demo的app,自动会生成一个leaks的程序,在测试时,会自动收集程序中的内存泄露。并且记录。记录的都是对象对应的引用位置,可以具体查看代码中的引用位置做分析
下面看一下LeakCanary的执行
我们是在Application install方法
会调用LeakCanary 中的 androidWatcher()方法然后进行如下的调用。
RefWatcher
new AndroidWatcherExecutor() --->dumpHeap()/analyze()(--->runAnalysis())--->Hprof文件分析
new AndroidHeapDumper()
new ServiceHeapDumpListener()

3.Lint分析工具

Inspect code 代码检测
检测资源文件是否有没有用到的资源。
检测常见内存泄露
安全问题SDK版本安全问题
是否有费的代码没有用到
代码的规范---甚至驼峰命名法也会检测
自动生成的罗列出来
没用的导包
可能的bug
这部分中具体的就不做介绍了,直接翻译英文就基本可以理解

Specify Dependencies
在打开当前的类比如MainActivity,在选择的时候,可以直接选的对应的类
查看当前的类中写的引用

注:
Shallow Size
对象自身占用的内存大小,不包括它引用的对象。
针对非数组类型的对象,它的大小就是对象与它所有的成员变量大小的总和。当然这里面还会包括一些java语言特性的数据存储单元。
针对数组类型的对象,它的大小是数组元素对象的大小总和。

Retained Size
当前对象大小+当前对象可直接或间接引用到的对象的大小总和。(间接引用的含义:A->B->C, C就是间接引用)
换句话说,Retained Size就是当前对象被GC后,从Heap上总共能释放掉的内存。
不过,释放的时候还要排除被GC Roots直接或间接引用的对象。他们暂时不会被被当做Garbage。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容