JVM是一个规范,或者符合该规范的实现,或者以这样的实现运行的实例。JVM规范中并没有规定要使用各种GC机制;或者说,JVM规范写明了符合规范的JVM实现要提供自动内存管理的功能,但并不一定要有某种特定的“GC”。
而Dalvik虚拟机是一个具体的实现,即便是在同一个JVM中也会有多个GC的实现。例如Oracle的HotSpot VM中根据不同的使用场景而实现了不同算法的GC。在Dalvik VM 1.0版本中,使用的GC算法是没有分代的“标记—清除”(Mark Sweep),对堆上数据进行准确式(Exact/precise)标记,对栈/寄存器上数据进行保守式(Conservative)标记。标记的内容可以参考文件dalvik/vm/alloc/MarkSweep.c中的如下注释。
许多GC实现都是在对象开头的地方留一小块空间给GC标记用,而Dalvik虚拟机则不同,在进行GC的时候会单独申请一块空间,以位图的形式来保存整个堆上的对象的标记,在GC结束后就释放该空间。(www.daowen.com)
在标记阶段,从根集合开始,沿着对象用的引用进行标记直到没有更多可标记的对象为止。标记结束后,被标记到的就是活着的对象,没被标记到的就是“垃圾”。在清除阶段,Dalvik 虚拟机并不直接对堆做什么操作,而是在一个记录分配状况的位图上把被认为是垃圾的对象所在位置的分配标记清零。为了不让这个位图太大,位图中并不是每一位对应到堆上的一个字节,而是对应到一块固定大小的空间。为此,堆空间的分配也是有一定的对齐的。
只进行“标记—清除”工作,在经过多次GC后可能会使堆被碎片化。Android所实现的libc(称为Bionic)对这种情况有特别的实现,可以避免碎片化这一问题的发生。其实Dalvik 虚拟机的根源还是在JVM上,只要能符合规范,正确执行Java的.class文件的就是JVM。那么Android开发包中的dx与Dalvik虚拟机结合起来,就可以看成是一个JVM了。如果去阅读Dalvik虚拟机的文档,会发现其中有很多引用到JVM规范的地方,而且整体设计都考虑到了与JVM的兼容性。它与JVM规范的规定最大的不同在于它采用了基于寄存器的指令集,而JVM采用了基于栈的指令集。这可以看作是专门为ARM而优化的设计。Dalvik虚拟机要省内存和省电,有很多设计都是围绕这两个目标来进行的。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。