一,内存
1,内存泄露(Memory leak)
程序在向系统申请分配内存空间后(new),在使用完毕后未释放,结果导致一直占据该内存单元,我们和程序都无发再使用该内存单元,知道程序结束,这就是内存泄露
2,内存溢出(out of memory)
程序向系统申请的内存空间超出了系统能给的,如一个电梯能容纳8人,你要做10人,那么肯定不行的
大量的内存泄露会导致内存溢出
3,java程序的内存使用
java是JVM所虚拟出来的内存运行环境,JVM的内存可以分为三个区:堆内存(heap),栈(stack)和方法区(method)
栈:是简单的数据结构,但是在计算机中使用很广泛,栈最显著的特征就是先进后出,栈中只存放基本的类型和对象的引用
堆:堆内存用于存放有new创建的对象和数组,在堆中分配的内存,有java虚拟机自动化垃圾回收机制来管理(GC),JVM只有一个堆区被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身
方法区:又叫静态区,跟堆一样,被所有的线程共享,方法区包含所有的static变量
4,垃圾回收机制
垃圾回收机制(GC)可以自动清空堆中不再使用的对象,在java中对象是通过引用使用的,如果再没有引用指向该对象,那么该对象就无从处理或者调用该对象,这样的对象称为不可到达。垃圾回收于释放不可到达的对象所占据的内存
二,命令
1,adb shell cat /proc/meminfo 查看设备内存使用情况,一般来说这个是查看整机的内存,我们通常是关注我们app的占用内存情况
MemTotal:可以使用的内存总和(小于实际内存,操作系统预留了一部分)
MemFree:空闲的内存
Buffers:缓存
Cached:缓存
SwapCached:交换内存,一般是没有值的
2,adb shell dumpsys meminfo +包名 查看某个应用的内存使用信息
说明:
MEMINFO in pid 4720 [com.subject.zhongchou] ** 告诉我pid号
表示总内存
私有内存
交换内存
堆内存,前面一个是总的堆内存,后两个是堆分配的内存
原生的界面所占用的内存
底层的框架占用的内存
Apk中文件占用的内存
总数记录的值
这是内存占用的一个详情
二,采集内存数据
在sdk/tools/目录下有一个monitor这个工具,直接双击打开,或者可以使用DDMS
DDMS全称是Dalvik Debug Monitor Service ,可实现IDE与连接终端设备(包含仿真器与真机)的调试,DDMS可以实现查询终端设备运行状态,终端设备进程状态,现成状态,文件系统,日志信息等,以及控制终端设备,完成一些操作,总的来说他是一款性能分析工具,可以帮助开发者快速了解APP的运行状况。在SDK/tools/ddms.bat,双击就可以打开
不管使用哪个工具,打开都是一样的界面
1,堆内存
不断的操作app,就可以看到内存的变化了,我们可以捕获一个过程,记录整个内存的使用情况
我们可以点击一次GC,回收垃圾,正常回收内存就会变小,如果不变小,就说明有很多不可回收的对象
导出内存数据文件:点击红色箭头,就可以弹出框输出一个.hprof结尾的文件
2,内存的分析
内存分析的工具:Eclipse Memory Analysis Tools(MAT),这是分析java堆数据的专业工具,用它可以定位内存泄露的原因。地址:http://www.eclipse.org/mat/downloads.php
根据自己的版本去下载
因为.hprof这个文件不能直接分析,所以要用SDK中platform-tools中的hprof-conv.exe进行转换
在cmd中输入hprof-conv xxx.hprof(内存源文件) xxx.hprof(新文件名)。回车就可以了,如图:
这个时候就可以使用Eclipse Memory Analysis Tools(MAT)打开刚才的转换后的文件了,如图是正在解析的一个过程
解析过程中会出现如下弹框,点击取消就行,如图:
下图就是解析完后后的一个内存报告:
往下拉就出现下面的图解,这是一些详细的说明
这里有各种类别的报告,如top级别的,可以看到占用内存最大的程序
我们点击红框中的一个系统级别的报告,可以看一下,这里面会直接告诉我哪些有问题,我们就可以根据这个详细的分析
在这里我们需要和历史数据做对比,需要对收集几次内存,然后进行对比,具体对比操作如下:
这里可以选择add to compare basket,可以添加历史文件进来
这样就可以看出来前后两次操作,看到各个对象所占用内存的变化了