一、简介
dalvik是google在其android智能手机操作系统中用的java虚拟机。借此讲一下我对虚拟机的基本理解吧。一切编程语言要想在计算机上运行必须翻译成机器码(这是废话)。java是一种半编译半解释型语言。半编译是指:java源代码,会经过javac命令变成 .class文件。半解释是指: .class文件被jvm解释的过程。也就是因为jvm的半解释才有了java的动态语言特性:反射和annotation。
二、类文件预处理
在半编译阶段,java源代码被编译,在.class文件中会有类信息和虚拟机指令。dalvik有自己的libdex库负责对.class进行处理。libdex主要对.class进行处理生成自己的dex文件。主要做的工作是,对虚拟机指令进行转换(dalvik是基于寄存器的,sun虚拟机是基于栈的),对类的静态数据进行归类、压缩。
三、类加载
在虚拟机启动时,根据输入的参数(一般有入口类(main函数所在的类)和jar包的路径),在classath路径中加载入口类,类加载过程是:虚拟机根据入口类的全称,去遍历classpath下的dex文件(dalvik第一次加载后会生成cache文件,供下次快速加载,所以第一次会很慢),获取入口类的信息,构建入口类的Class结构体,Class结构主要包含类的field、method、(anntation 和内部类dalvik放在native处理,没在Class结构体,这样为了节省内存)。另外在加载入口类之前,可能要加载,他所依赖的类,比如父类、Class类等,类被加载后一般会在classloader中保存,下次用可以直接取到。
- filed主要信息,filed的类型、变量名对static fiedl 还有可能有初始值(非static field在构造函数中赋初值,不保证每个类都有静态初始化块<clinit>方法,所以staitc filed初始值要单独处理)。
- method 主要有:方法签名、method Code(虚拟机指令)、exception等信息
- const、const-string等:一般是把一个常量(int double short boolean char string ……),放入一个寄存器。
- add sub div xor or and ……:加减乘除、与或非等
- getfield putfield 、getstatic putstaic:在堆上获取相应对象的field值,对static可能在Class结构体内存放
- invokeXXX:调用某个方法,要在栈上保存当前frame信息(包括IP 及各寄存器值),push一个frame去解释另一个方法。方法调用是,要将这个方法的参数copy到新的frame 寄存器上。在被调用的方法结束时,在栈上pop出该frame,把方法返回值copy到调用frame的寄存器上。(这个可以有多种实现,dalvik是把返回值copy到全局的ret变量中,在用move_result指令来做到这一点)
- return :告诉解释器方法调用结束
- if if_eqz等:逻辑判断、还有swith case等也有专门指令
- new指令,new一个对象放在堆上