《逆向分析》 Android Dalvik虚拟机

时间:2021-12-14 17:06:42

       Dalvik虚拟机的特点--Android应用程序的运行原理

        

       虚拟机特点:

               # 体积小,占用内存空间小

               # 专有的DEX可执行格式,体积更小,执行速度更快

               # 常量池采用32位索引值,寻址方法名,字段名,常量更快

               # 基于寄存器架构,并有一套完整的指令系统

               # 提供了对象生命周期管理,堆栈管理,线程管理,安全和异常管理以及垃圾回收等重要功能

               # 所有的Android程序都运行在Android系统进程里,每个进程对应着一个Dalvik虚拟机实例  


       Dalvik虚拟机与Java虚拟机的区别

               1. Java虚拟机运行的是Java字节码,Dalvik虚拟机运行的是Dalvik字节码。

                传统的Java程序经过编译,生成Java字节码保存在class文件中,Java虚拟机通过解码class文件中的内容来运行程序 。而Dalvik虚拟机运行的是Dalvik字节码,所有的Dalvik字节码由Java字节码转换而来,并被打包到一个DEX(Dalvik Executable)可执行文件中。Dalvik虚拟机通过解释DEX文件来执行这些字节码。

                2. Java虚拟机与Dalvik虚拟机架构不同

                Java虚拟机基于栈架构。程序在运行时,需要频繁地从栈上读取或写入数据,这个过程需要更多的指令分派与内存访问次数,会消耗不少CPU时间,对于像手机设备资源有限的设备来说,这是相当大的一笔开销。

                Dalvik虚拟机基于寄存器架构。数据的访问通过寄存器间直接传递,这样的访问方式比基于栈方式要快很多。

                对于Java程序而言,每个线程在执行时,都有一个PC计数器与一个Java栈。PC计数器以字节为单位记录当前运行位置距离方法开头的偏移量,它的作用类似于ARM架构CPU的PC寄存器与x86架构CPU的IP寄存器,不同的是PC计数器只对当前方法有效,Java虚拟机通过他的值来取指令执行。Java栈用于记录Java方法调用的“活动记录”,Java栈以帧为单位保存线程运行的状态,每调用一个方法,就会分配一个新的栈帧压入Java栈上,每从一个方法返回,则弹出并撤销相应的栈帧,每个栈帧包括局部变量区,求值栈和其他一些信息,局部变量区用于存储方法的参数和局部变量,其中参数按源码中从左到右的顺序保存在局部变量开头的几个slot中。求值栈用于保存求值的中间结果和调用别的方法的参数等。

                Dalvik虚拟机运行时,同样为每个线层维护一个PC计数器和调用栈,与Java虚拟机不同的是,这个调用栈维护一份寄存器列表,寄存器的数量在方法结构体的register字段中给出,Dalvik虚拟机会根据这个值来创建一份虚拟的寄存器列表

                由此可见,给予寄存器架构的Dalvik虚拟机与基于栈架构的Java虚拟机相比,由于生成的代码指令少了,程序执行速度会更快一些。


        Dalvik虚拟机是如何执行程序的

        Android系统的架构采用分层的思想,这样的好处是减少各层之间的依赖性,便于独立分发,容易收敛问题和错误等优点。Android系统优Linux内核,函数库,Android运行时,应用程序框架和应用程序组成。Dalvik虚拟机属于Android运行时环境,它与一些核心库共同承担Android应用程序的运行工作。

        Android系统启动加载完内核后,第一个执行的是init进程,init进程首先要做的是设备的初始化工作,然后读取inic.rc文件并启动系统中的重要外部程序zygote。zygote进程是Android所有进程的孵化器进程,它启动后会首先初始化Dalvik虚拟机,然后启动system_server并进入Zygote模式,通过socket等候命令。当执行一个Android应用程序时,system_server进程通过socket方式发送命令给Zygote,Zygote收到命令后通过fork自身,创建一个Dalvik虚拟机的实例来执行应用程序的入口函数,这样一个程序就启动完成了。