admin管理员组

文章数量:1531747

一、Dalvik虚拟机特点–掌握Android程序运行原理

1 什么是Dalvik虚拟机?

Google于2007年正式发布Android SDK,Dalvik虚拟机进入人们视野,名字源于一个叫Dalvik的小渔村,还有一种好听的名字叫做冰岛。Dalvik作为Android平台的核心组件,有很多特点:

  1. 体积小
  2. 专有的dex可执行文件格式,体积更小,执行速度更快。
  3. 常量池采用32位索引,拥有一套完整的指令系统。
  4. 所有的Android程序都运行在Android系统进程里,每个进程对应一个Dalvik虚拟机实例。

2 Dalvik虚拟机和Java虚拟机的区别

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

Java程序字节码保存在class文件中,Java虚拟机通过解码运行程序,而Dalvik虚拟机运行的是相应的Dalvik字节码,所有的Dalvik字节码都是由Java字节码转换过来的,被打包到一个dex可执行文件中,通过解释dex文件来执行程序。

2.Dalvik可执行文件体积更小

SDK有一个dx工具可以将Java字节码转换为Dalvik字节码,dx工具可以将Java类文件中常量池分解,冗余的信息剔除,重新组合一个常量池,所有文件共享一个常量池。如下图:



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

Java虚拟机基于栈架构,Dalvik虚拟机基于寄存器架构。
Java频繁的从栈上读写数据,需要更多的指令分派和访存次数,开销大,Dalvik虚拟机通过寄存器间直接传递,比栈方式快很多,如下代码通过测试对比:

public class Hello{
    public int foo(int a,int b){
        return (a+b)*(a-b);
    }
    public static void main(String[] argc){
        Hello hello=new Hello();
        System.out.println(hello.foo(5,3));
    }
}

用命令

javac Hello.java

将其编译成class文件后,用命令dx(在android-sdk-windows\build-tools\23.0.2下,添加path就行)生成dex文件:

dx --dex --output=Hello.dex Hello.class

可能会提示class文件无效,因为jdk1.8编译的class文件默认会比较低,所以用重新编译

javac -source 1.6 -target 1.6 Hello.java

之后用命令反编译class文件:

javap -c -classpath . Hello

执行后的如下代码(Java class文件):

public int foo(int, int);
    Code:
       0: iload_1(iload+1->i表示类型 iload表示将int型数据进栈)
       1: iload_2
       2: iadd
       3: iload_1
       4: iload_2
       5: isub
       6: imul
       7: ireturn

使用

dexdump.exe -d Hello.dex

整理后的结果(Dalvik dex文件):

Hello.foo:(II)I
0000: add-int v0, v3, v4
0002: sub-int v1, v3, v4
0004: mul-int/2addr v0, v1
0005: return v0

每条指令占一个字节,可以看出:Java占了8个字节,8条指令,而Dalvik用了4条指令就完了。

解读(java-class):



iload_1和iload_2将第一个第二个参数入栈局部变量区,iadd降低一个第二个参数相加结果送入求值栈顶,之后再次将两个参数入栈,isub将两个参数相减送入求值栈顶,imul将求值栈顶两个元素相乘结果压入求值栈顶,做后得到结果16.

解读(dex):



相比Java,Dalvik简单多了,将v3 v4(两个参数)相加值给v0,v3v4相减给v1,最后v0*v1得到结果。

所以Dalvik虚拟机比Java虚拟机代码少,速度会更快一点。

3 Dalvik如何执行程序?



Android程序第一步加载init进程,初始化设备,读取inic.rc文件启动Zygote。Zygote是Android进程孵化器,它启动后首先初始化Dalvik虚拟机,然后启动system_server 进入Zygote模式等候socket命令,当得到命令后会fork自身新建一个Dalvik虚拟机来执行程序的入口函数,这样一个程序就启动了

二、Dalvik汇编语言基础

1 DEX 文件反汇编工具

BakSmali和Dedexer,两种反编译效果都不错,但是推荐用BakSmali,因为BakSmali命名法比较容易区分局部变量(v0,v1…表示)和函数参数(p0,p1…),后者不区分,还支持打包重新生成dex文件,可广泛用于apk修改破解。

2 Dalvik寄存器

Dalvik寄存器都是32位的,64位类型用两个相邻的寄存器表示,根据语法格式:op vAAAA,vBBBB ,一个字母代表4位,最多有2的16次方,65535个寄存器。

3 两种寄存器命名规则-v命名法和p命名法

一个函数用到M个寄存器,函数参数N个,Dalvik虚拟机传参方式规定:参数使用最后面N个寄存器,局部变量从v0开始的M-N个。

v命名法:从局部变量到隐式函数对象占一个寄存器,后面的位函数参数,v0,v1,v2,v3,v4….

p命名法:局部变量用v1,v2… 表示, p0表示对象的引用,p1,p2…表示函数参数

所以p命名法比v命名法好一点易于区分局部变量和函数参数。

4 Dalvik字节码类型,方法,与字段表示方法

详见博客:http://yrldrops.xyz/2018/10/28/Smail语法/#more

相关知识详细参考《Android软件安全与逆向分析》

你的支持是我最大的动力!

支付宝 微信

本文标签: 虚拟机androidDalvik