1.Stack和Heap
stack:栈
特点:
- 栈内存,操作系统来分配和释放,
- 存声明对象,栈内存分配地址空间
- 几M大小就够,速度最快
- 垃圾回收GC频繁
heap:堆
特点:
- 堆内存,程序员自己手动申请和释放
- 每当new一个对象实例,就在堆内存分配地址
- 空间大,速度慢
- 垃圾回收GC不频繁
要释放内存的唯一方式,是释放app持有对象的引用以便于垃圾回收器回收
- native heap:lib层c /c++库占用。 、/system/bin下程序也是native进程形式存在 (c/c++),非java分配的内存都在这
- Dalvik heap:Dalvik虚拟机使用内存,堆内存,java实例对象空间 (java)
- Dalvik other:数据结构和索引
- so mmap:native 代码和常量
- dex mmap:java代码和常量
profiler中参数
Graphics:图形缓冲区队列占用的内存
Java heap中
ps:测试开始时,先手动gc一次,观察数据准确
Allocations:堆中的实例数
native size:c/c++堆占用大小。主要显示bitmap所用的像素内存(安卓8.0以上算在这里{为了降低OOM},以下还在java堆中)
shallow size:所有实例的总大小(真实java堆内存。以string、数组等基本类型居多)
retained size:为当前这个实例保留内存的大小(大得多,因为有重复计算的),如果GC把当前对象回收,则释放当前大小的内存
class name:
BitMap:图像处理类,获取图像信息,图像剪切,旋转,缩放操作
测试关注点
1. 内存抖动
- 短时间创建大量对象,又迅速被释放
2. 内存泄露
- 卡顿,响应慢。由于内存高时候频繁GC
- 莫名消失。因为内存占用大,被系统优先级后台处理kill
- Crash。该释放的资源没释放,内存增高不降,导致内存浪费
测试方法:
- adb shell dumpsys meminfo (package name)
- 反复进出要测试的场景,使用adb查看views和activities数量,是否有相应的减少
3. 内存溢出
- OOM,超过进程最大内存限制就会出现
单个应用可用最大内存:查看命令:adb shell getprop | grep dalvik.vm.heapgrowthlimit
如果存在heapgrowthlimit,则以它为准。
ps:
1.oom原因之一:程序申请的java heap堆内存超过了厂家设定的dalvik单个进程(或单个虚拟机)最大堆内存dalvik.vm.heapsize,heapsize为极限堆
查看命令:
2.系统仅对dalvik进程java heap做了限制,并未对native堆做限制,可以设native堆很大
3.ram不足:通过memory killer杀优先级低的进程来释放内存
2.JVM、Dalvik、Art
JVM
- 基于栈,编译成字节码.class ,打包到.jar文件
- java虚拟机从.class和.jar获取字节码
Dalvik
- 基于apache的java虚拟机,
- 运行是专属.dex字节码格式(java类编译.class后,由dx工具转换为.dex)
- 每次应用运行,字节码都需要即时编译机器码
- 占用空间比art小
Art
- android 4.4发布的
- 首次启动编译
- 空间换时间,比dalvik大
- 应用启动更快,更流畅,触感及时
3.paging 和 memory-mapping (分页和内存映射)
4.LruCache缓存作用
1.为啥用缓存?
答:比如网络请求图片,发起请求,等待响应,接收数据,解析数据,显示数据。 放子线程里操作
有了缓存,无非就是添加/删除/获取 缓存,先判断有没有缓存,没有就添加,满了就把很久没使用的删掉
2.两种缓存方式
- 1.内存缓存:速度最快,从内存中拿数据
- 2.磁盘缓存: 慢一点,因为有IO流操作,但是可以做持久化数据
3.LruCache
- 近期最少使用算法。
- 优先清除最近很少使用的对象
- 也是2种,针对内存LruChe,针对磁盘LruChe