Android内存管理机制的定义
- 内存的分配
- 内存的回收
管理机制的说明
管理的内存对象
- 进程
- 对象
- 变量
管理的角色
Android 系用可分为三个层次分别为:Application Framework、Dalvik、Linux内核
负责管理进程内存
- Application Framework
- Linux
负责管理对象、变量内存
- Dalvik虚拟机
内存管理的详细分析
进程内存管理
内存的分配策略
- 由ActivityMangerService集中管理所有进程的内存分配
内存的回收策略
-
Application Framework 决定回收的进程类型
当进程的内存空间紧张的时候,会按照进程的优先级从低到高的顺序依次自动去做回收
前台进程 (最高)
可见进程
服务进程
后台进程
空进程(最低)
-
Linux内核做进程的回收
- ActivityManagerService对所有进程做评分
- 将分数更新到Linux内核中
- 由Linux内核完成真正的回收
对象、变量的内存管理
- Android对于对象、变量的内存管理策略同于Java。
- 内存管理 == 对象、变量的内存分配和内存的释放。
内存分配策略
-
Android中对象、变量的内存分配由程序自动完成。
-
三种分配
-
静态分配:面向静态变量
-
栈式分配:面向局部变量
-
堆式分配:面向对象实例
-
具体描述如下
内存分配策略 使用的内存空间 存储的数据 分配策略描述 静态分配 方法区<br />(静态存储区) 存储已经被虚拟机加载的类信息,常量和静态变量 在程序编译时就已经分配好以及存在于整个运行期间<br />(不需要回收) 栈式分配 栈区 存储方法执行时的局部变量(含数据类型、对象引用)<br />(已帧栈的形式) 1. 方法执行时,定义的局部变量由程序自动在栈中分配内存<br />2. 方法只是结束后/超出变量域时,由栈帧自动释放该部分的内存<br />3. 效率高(栈内存分配运算置于处理器的指令中)<br />4. 分配的内存容量有限 堆式分配 堆区 存储Java对象的实例以及对象内部的成员变量<br />1. 采用关键字 new出来的对象<br />2. 实例的成员变量= 基本数据类型、引用以及引用的对象实体 1. 创建对象实例时,由程序分配<br />(由Java垃圾回收管理器自动管理;不使用时则回收)<br />访问方式<br />1. 创建一个对象,在堆内存中存放首地址在栈内存中定一个饮用变量;<br />2. 通过引用变量来访问堆内存中的对象/数组 - 代码实例讲解
public class MemoryManageClass { int s1 = 0; MemoryManageClass mClass1 = new MemoryManageClass(); public void method(){ //变量s2、mClass2 都存放在栈内存中 int s2 = 0; //变量mClass2 所指向的对象实例存在堆内存中 //该对象的实例中的成员变量 s1和mClass1 也放在堆中 MemoryManageClass mClass2 = new MemoryManageClass(); } } // mClass 变量存放在栈中,mClass变量指向的对象实例存放在堆中 //该对象实例中的成员变量 s1 mClass1 存放在堆中 MemoryManageClass mClass = new MemoryManageClass();
-
内存释放策略
- 变量/对象的内存释放右Java的GC/栈帧负责回收
- 静态分配不需要释放,栈式分配由栈帧自动出、入栈。
- 堆式分配的内存释放原则 == Java的垃圾回收器(GC)
- Java垃圾回收器的内存释放 主要有垃圾回收算法来完成
垃圾回收算法
- 标记-清除 算法
- 复制 算法
- 标记-整理 算法
- 分代收集 算法
具体算法介绍
算法名称 | 算法思想 | 优点 | 缺点 | 应用场景 |
---|---|---|---|---|
标记-清除 | 1. 标记阶段:标记出所有需要回收的对象<br />2. 清除阶段:统一清除(回收,释放)所有被标记的对象 | 实现简单 | 1. 效率问题:标记和清除阶段效率不高<br />2. 空间问题:标记 清除后,会产生大量不连续的内存碎片 | 对象存活率低一级垃圾回收行为频率低 |
复制 | 1. 将内存分为大小相等的两块,每次使用其中一块<br />2. 当使用的这块内存用完,就将这块内存上还存活的对象复制到另一块还没使用的内存上<br />3. 最终将使用那块内存一次清除掉。 | 1. 解决了算法1中的清除效率低的问题;每次仅仅回收内存的一半区域<br />2. 解决了算法1中 因清除而产生的不连续内存碎片的问题;将已经使用内存上的存活对象移动到栈顶的指针,按顺序分配内存即可。 | 1. 每次使用的内存缩小为原来的一半<br />2. 当对象存活率较高的情况下需要做很多复制操作,效率会变低。 | 对象存活率较低 以及需要频繁进行垃圾回收的区域 |
标记-整理 | 1. 标记阶段:标记出所有需要回收的对象<br />2. 整理阶段:让所有存活的对象都向一端移动<br />3. 清除阶段:统一清除端以外的对象 | 1. 解决了算法1中清除效率低的问题,一次性清除端以外区域的对象<br />2. 解决了算法1中 空间中产生不连续内存碎片的问题。 | 步骤繁多:标记 整理 清除 | 对象存活率较低 一级 垃圾回收行为频率低的 |
分代收集 | 1. 根据对象存活周期的不同将Java堆内存分为:新生代和老年代<br />2. 每块区域的特点如下<br />新生代: 对象存活率较低 以及 垃圾回收行为频率较高<br />老生代:对象存活率较低 以及 垃圾回收行为频率低<br />3. 根据每块区域的选择对应的算法<br />新生代:复制算法<br />老生代:标记-清除 标记-整理 | 效率高,空间利用率高;根据不用区域特点选择不同垃圾收集算法 | 主流的虚拟机基本都使用该算法 |
网友评论