一、数据在内存中的位置
Dalvik内存数据保存在6个位置上:
- 寄存器:位于处理器内部;速度最快,开发人员没有直接控制权。
- 栈:位于RAM,速度仅次于“寄存器”;使用的是一级缓存,需要在创建的之前知道占用的内存大小和存活时间;存放引用,实际数据存在堆中; 他们通常都是被调用时处于存储空间中,调用完毕立即释放。
1)系统栈(也叫核心栈、内核栈)是内存中属于操作系统空间的一块区域,其主要用途为: (1)保存中断现场,对于嵌套中断,被中断程序的现场信息依次压入系统栈,中断返回时逆序弹出; (2)保存操作系统子程序间相互调用的参数、返回值、返回点以及子程序(函数)的局部变量。
2)用户栈是用户进程空间中的一块区域,用于保存用户进程的子程序间相互调用的参数、返回值、返回点以及子程序(函数)的局部变量。 - 堆:位于RAM,速度次于“栈”;存放在二级缓存中,创建前不需要知道大小和时间,所以在分期配存储空间的时候会消耗一定时间,生命周期由虚拟机的垃圾回收算法来决定;存放被引用数据的实际内容。
- 静态域:位于RAM上的固定的位置;保存静态引用。
- 常量池:位于ROM;常量池指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。包含各种基本类型数据和常量值(final修饰的,字符常量,常量数组等),还包含一些以文本形式出现的符号引用:类和接口的全限定名、字段的名称和描述符、方法和名称和描述符、类的其他基本信息等。
(JVM中的常量池在内存当中是以表的形式存在的, 对于String类型,有一张固定长度的CONSTANT_String_info表用来存储文字字符串值,注意:该表只存储文字字符串值,不存储符号引用) - 随机存取存取器(非RAM存储):独立于程序之外,程序不存在时仍可存在,如文件或网络数据等。
二、Dalvik与JVM的内存机制比较
Dalvik内的方法区也与JVM内的一样,又叫静态区,被所有的线程共享;方法区中包含的都是在编译期被确定的,在程序中永远的唯一的元素,包含所有的类信息、静态变量、编译器编译出的代码以及部分常量。
Dalvik与JVM在内存机制上的区别在于:
- Dalvik的执行基于寄存器,而JVM基于虚拟机栈(栈帧)。Dalvik执行.dex(.odex)格式的字节码,是对.class文件进行压缩后生成的,Dalvik的编译和运行速度都会更快些。
- Dalvik的GC条件根据可达性分析算法确定(以根集对象为起始点进行搜索,如果有对象不可达的话,即是垃圾对象),而JVM上的GC则是根据程序计数器提供引用计数法(给一个对象添加引用计数器,每当有个地方引用它,计数器就加1;引用失效就减1。)。可达性分析算法较引用计数法更为复杂,但是可以很好的解决循环引用的问题。
三、回收算法:
- 标记回收算法(Mark and Sweep GC):从”GC Roots”集合开始,将内存整个遍历一次,保留所有可以被GC Roots直接或间接引用到的对象,而剩下的对象都当作垃圾对待并回收,这个算法需要中断进程内其它组件的执行并且可能产生内存碎片
- 复制算法 (Copying):将现有的内存空间分为两快,每次只使用其中一块,在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。
- 标记-压缩算法 (Mark-Compact):先需要从根节点开始对所有可达对象做一次标记,但之后,它并不简单地清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外所有的空间。这种方法既避免了碎片的产生,又不需要两块相同的内存空间,因此,其性价比比较高。
- 分代:将所有的新建对象都放入称为年轻代的内存区域,当一个对象经过几次回收后依然存活,对象就会被放入称为老生代的内存空间。年轻代的特点是对象会很快回收,因此,在年轻代就选择效率较高的复制算法,而对于老年代则采取标记-压缩算法。