Android Dalvik虚拟机的特点:

l  体积小,占用内存空间小。

l  专有DEX可执行文件。

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

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

l  提供生命周期管理、堆栈管理、线程管理、安全和异常管理以及垃圾回收等重要功能。

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

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

Java虚拟机运行的是Java字节码,Dalvik虚拟机运行的是Dalvik字节码。Dalvik字节码由Java字节码转换而来,并打包成一个DEX可执行文件,通过虚拟机解释执行。

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

Android SDK中的dx工具在转换字节码时会消除类文件的冗余信息,避免虚拟机在初始化时出现重复的文件加载与解析过程。另外,dx工具会将所有的Java类文件中的常量池进行分解,消除其中的冗余信息,组合成一个新的共享常量池。这使得文件体积和解析文件的效率都得到了提高。

3、Dalvik虚拟机与Java虚拟机的架构不同

Java虚拟机的架构及参数传递

Java虚拟机基于栈架构。需要频繁的从栈上读写数据,在这个过程中需要更多的指令分派与内存访问次数,耗费CPU时间,消耗手机资源。

Java虚拟机的指令集被称为零地址,是指指令的源参数与目标参数都是隐含的,它通过Java虚拟机中提高的一种数据结构“求值栈”来传递的。

对于Java程序来说,每个线程在执行时都有一个PC计数器与一个Java栈。PC计数器以字节为单位记录当前运行位置距离方法开头的偏移量,与ARM架构和x86架构类似,通过栈帧对栈中的数据进行操作。

Java栈用于记录Java方法调用的“活动记录”,Java栈以帧为单位保存线程的运行状态,每调用一个方法就会分配一个新的栈帧压入Java栈上,每从一个方法返回则弹出并撤销响应的栈帧。

每个栈帧包括局部变量区、求值栈(JVM规范中将其称为“操作数栈”)和其他一些信息。局部变量区用于存储方法的参数与局部变量,其中参数按源码中从左到右顺序保存在局部变量区开头的几个slot中。

求栈值用于保存求值的中间结果和调用别的方法的参数等,JVM运行时它的状态如下图

每条指令占用一个字节空间,foo()函数Java字节码左边的偏移量就是程序执行到每一行代码时PC的值,并且Java虚拟机最多只支撑0xff条指令。

仔细分析第一条指令iload_1的结构

iload_1可分成两部分,第一部分为下划线左边的iload,属于JVM(Java虚拟机)指令集中load系列中的一条,i是指令前缀,表示操作类型为int类型,load表示将局部变量存入Java栈。第二部分为下划线右边的数字,表示要操作具体哪个变量,索引值从0开始计数,iload_1表示将第二个int类型的局部变量进栈参数。

Dalvik虚拟机的架构及参数传递

Dalvik虚拟机基于寄存器架构,数据访问通过寄存器间直接传递。比起Java虚拟机字节码要简洁很多。

以第一条指令为例简单分析一下。指令add-int将v3与v4寄存器的值相加,然后保存到v0寄存器,v3和v4代表调用函数的所使用的两个参数。这里用到的Dalvik字节码参数表示法是v命名法,另一种是p命名法。

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

Dalvik虚拟机由于生成的代码指令减少了,程序执行速度会更快一些。

Dalvik是如何执行程序的

Android系统的架构采用分层思想,这样的好处是拥有减少各层之间的依赖性、便于独立分发、容易收敛问题和错误等优点。

Android系统由linux内核、函数库、Android运行时、应用程序框架以及应用程序组成。

Android系统加载完内核后,第一个执行的是init进程,init进程对设备进行初始化,读取init.rc文件并启动系统中重要外部程序Zygote。

Zygote进程是Android所有进程的孵化器,启动后首先初始化Dalvik虚拟机,然后启动system_server并进入Zygote模式,通过socket等候命令。

当执行一个Android应用程序时,system_server进程通过socket方式发送命令给Zygote,Zygote收到命令后通过fork自身创建一个Dalvik虚拟机的实例来执行应用程序的入口函数,这就是程序启动的流程。

Zygote提供三种

fork(),创建一个Zygote进程

forkAndSpecialize(),创建一个非Zygote进程(不能再fork)

forkSystemService(),创建一个系统服务进程(子进程跟随父进程终止)

fork之后,执行的工作交给Dalvik虚拟机。虚拟机通过loadClassFromDex()函数完成类的装载工作,每个类被成功解析后会拥有一个ClassObject类型的数据结构存储在运行时环境中,虚拟机使用gDvm.loadedClasses全局哈希表来存储与查询所有装载进来的类,随后,字节码验证器使用dvmVerifyCodeFlow()函数对装入的代码进行校验,接着虚拟机调用FindClass()函数查找并装载main方法类,随后调用dvmInterpret()函数初始化解释器并执行字节码流。

Dalvik虚拟机执行程序流程

虚拟机线程->装载程序类->验证字节码->查找主类->执行字节码流->结束

关于Dalvik虚拟机JIT

JIT是即时编译(动态编译),是通过在运行时将字节码翻译为机器码的技术,使得程序的执行速度更快。

主流的JIT包含两种字节码编译方式:

method方式:以函数或方法为单位进行编译。

trace方式:以trace为单位进行编译。

执行代码分为冷路径(在实践运行过程中很少被执行的)和热路径(执行比较频繁的路径),method会编译整个方法,trace编译的是获取的热路径的代码,节省内存。

编辑参考:Android软件安全与逆向分析

Android逆向基础----Android Dalvik虚拟机的更多相关文章

  1. Android ART运行时与Dalvik虚拟机

    这几天在做一个项目时需要在Android中使用OSGi框架(Apache Felix),于是在一个android 4.4.2 版本系统的某品牌的平板上实验. 实验内容很简单:把felix包里的feli ...

  2. Android虚拟机器学习总结Dalvik虚拟机创建进程和线程分析

    Dalvik调用一个成员函数时,虚拟机,假设发现,该成员函数是一个JNI办法,然后,它会直接跳转到其地址来运行.也就是说.JNI方法是直接在本地操作系统上运行的.而不是由Dalvik虚拟机解释器运行. ...

  3. Android逆向基础----APK文件结构

    参考这个博客 http://www.cnblogs.com/wangtianxj/archive/2010/06/13/1757639.html http://blog.csdn.net/bupt07 ...

  4. Android逆向基础----Dalvik字节码

    参考此微博,更多详细内容可以到这里查看 http://blog.csdn.net/dd864140130/article/details/52076515 Dalvik字节码 1.寄存器位32位,64 ...

  5. Android逆向基础知识Smali

    什么是Smali: 我们用工具反编译一些APP的时候,会看到一个smali文件夹,里面其实就是每个Java类所对应的smali文件.Android虚拟机Dalvik并不是执行java虚拟机JVM编译后 ...

  6. android逆向基础:apk 反编译 重打包 重签名

    apk 反编译大家都比较熟悉,这里只做一个笔记. 1 反编译 apk apktool d perfect.apk 这样就把资源文件解压缩了, classes.dex 也反编译成了 smali 文件 2 ...

  7. 4. 移动安全渗透测试-(Android逆向基础)

    4.1 smali 基础 1.注释 smali中使用#来代表注释一行例如:# const-string v0, "aaa" #这句不会被执行 2.数据类型 V void,只能用于返 ...

  8. Android逆向学习资料

    Android逆向基础之Dalvik虚拟机: https://lyxw.github.io/archivers/Android%E9%80%86%E5%90%91%E5%9F%BA%E7%A1%80% ...

  9. Android Dalvik 虚拟机

    简介 Android 平台虽然是使用java语言来开发应用程序,但Android程序却不是运行在标准java虚拟机上的.谷歌专门为Android平台设计了一套虚拟机来运行Android程序.它就是Da ...

随机推荐

  1. Ubuntu下使用sublime text进行py开发

    放弃了,半天弄不出一个方便的开放环境,还是现成的iDE方便 下载方法 https://www.sublimetext.com/docs/3/linux_repositories.html 首先安装Pa ...

  2. C++对象作为返回值的问题

    #include "stdio.h" class Object{ public: int i; Object& method1(){ return *this; } }; ...

  3. Gym102082 G-What Goes Up Must Come Down(树状数组)

    Several cards with numbers printed on them are lined up on the table. We’d like to change their orde ...

  4. HTML学习笔记Day1

    一.网站建设流程 1.注册域名(网址) 2.租用空间(服务器) 3.网站建设 (1)确定网站主题(项目) (2)搜集材料(项目) (3)规划网站(UI) (4)制作页面(前端--后端) 4.网络推广 ...

  5. php处理文件上传

    注意点: 1.<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" ...

  6. go 方法

    go 方法 Golang中的任何自定义类型,都可以有方法,而不仅仅是struct. 定义:func (recevier type) methodName(参数列表)(返回值列表){} 方法的访问控制, ...

  7. docker的使用 -- windows

    1. 下载docker desktop https://www.docker.com/products/docker-desktop 更多操作指令 ps: 值得注意的是,刚下载下来的docker只能在 ...

  8. 基于jieba,TfidfVectorizer,LogisticRegression进行搜狐新闻文本分类

    一.简介 此文是对利用jieba,word2vec,LR进行搜狐新闻文本分类的准确性的提升,数据集和分词过程一样,这里就不在叙述,读者可参考前面的处理过程 经过jieba分词,产生24000条分词结果 ...

  9. 设计模式---状态变化模式之state状态模式(State)

    前提:状态变化模式 在组建构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定?“状态变化”模式为这一个问题提供了一种解决方案. 典型模式 状态模式:Stat ...

  10. SonarQube(代码质量管理)配置与使用

    继 Sonarqube(代码质量管理)环境搭建,交大家如何配置与使用Sonarqube 1: 汉化Sonarqube: 找到 Setting --> Update Center --> A ...