Android虚拟机之Dalvik初识

Advertisement

本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!

研究安卓已多年,一直在应用层做开发,Framework层只是看过,也就是大家常说的"底层",而高级一点的功能如热加载、处理器类型配置,必须得了解再深入些才好,Library、Runtime、Kernel层等;当然了解底层的原因,不是在于去做底层开发,而是更好的做应用层,使其功能更强大和完善。这里的底层是除应用层以外其他层。而Dalvik是什么,就是把各层串起来,处理安卓系统和服务的一个计算机。

Dalvik这个名字,是创始人的祖先生存过一个小村庄的名字,大概为纪念先人的原因,这个村庄位于冰岛。前面也有讲这个虚拟机是专门为移动设备,即内存小、计算能力低、运行标准要求高提供的嵌入式设备,正因为克服如此多的问题,以其优良的性能出现在世人面前,才受到众多厂商的追捧,前有HTC、摩托罗拉,后来阿里云、小米;越来越追求代码层的优化,更好的解决方案,更快的解释和加载速度,更好的体验和兼容性,来抵消硬件设备带来的价格冲击-这也是国内厂商,应对众多街机的一种战略手段,以数十万上百万的出厂设备*单利-有限的研发力量价格=最终厂家利润,假设每件研发投入100万,价格降低5块,则收益至少达到平衡或500万以上;个人不太认同这种恶性竞争,逼死开发的策略,商品应该优质高价,让消费者使用安全放心,带给的是心理的安全感、舒适感、品牌感知度,以及强大的功能,像IPhone一样,让生活归生活,功能归功能;所以从厂商竞争情况来说,个人觉得华为做的最好。但万变不离其宗,产品总是不完善的,需要维护和升级,以维持其对于公众的领先地位,因此理解虚拟机,有助于从全局出发,提出更好的优化或解决方案,为消费者提供更好的产品。

闲话这么多,进入正题。Dalvik来自于JVM,大多数的java程序都可以执行(为什么说大多数,因为它退出JSF标准,按说1.6以后是否全面的支持Java,这事能肯定)。前面对JVM有过讲解,它基于堆栈,处理代码指令,需要不断的从主内存复制到临时内存,然后操作完再存回去,有寄存器但仅限于虚拟机自己使用;而Dalvik基于寄存器,代码的执行本身就依赖于寄存器,且避免过多的存取,字节码指令减少47%,访问次数减少37%,因为执行速度更快。但寄存器有一个缺陷,只有65536个,每个32位,即总共256k,因此它还需要另一种文件Odex的支持。说到它,就得先讲dex文件,我们都知道java文件被编译后形成.class文件,这种文件符合JVM的执行规则;而Dalvik则把.class文件使用dx工具压缩形成dex文件,它符合寄存器的执行规则,同时又是对原数据进行过优化,共享共同数据,降低冗余,使用代码结构紧凑,因而包大小大约为同类型jar文件的50%。

Dex文件的格式与前面讲的类文件格式类似,可以对比着看:有基本数据类,如byte占8位,表示1byte的有符号数,ubyte同样,但表示无符号数;也有文件结构,也有字符串索引,字段索引,方法索引,类型索引,类定义,多的是原型数据索引,连接数据区等;同时header信息里也存着魔数,文件总长度,以上各种索引及类型的个数、地址等,索引除公用的是绝对位置,其他均为相对位置。数据的存放。Dalvik字节码总共有226条,使用时会用一个hash指令表来存储,格式如 B|A|op 12x 第一个是指令,第二个是缩写,用来说明它的操作逻辑。

Odex文件是为了提高程序执行速度而做的本地缓存,一般存在data/dalvik-cache/xxx.odex,这个文件已经由寄存器加载时帮忙做过字节码校验、空方法消除、替换优化等工作,执行时优化解释odex,没有再执行dex,把加载过的字节码缓存入odex,这就是它的工作原理。它在Dex文件前添加了头部信息,尾部拼接了依赖库、寄存器映射关系、类hash索引等辅助信息,索引再介绍一下,它包括文件的偏移地址和类的偏移地址,通过hash定位可以尽快查找到资源并加载。讲到这里,dex加载的原理已经明了,由Dalvik加载,处理器解释执行,缓存放入odex。而Odex不断增大,也是安卓手机内存变小的原因,因而对于卸载的App的odex文件可以删除,不常用的选择删除,常用的保留,不然每次加载解释后仍然会增大,而手机速度更慢。

dex是重点,而apk的组成还有主配置文件,资源文件,通过aapt工具打包而成,用jarsigner签名。而dex的加载跟class文件加载非常类似,把Dex(class)与一个DexFile(ClassFile)文件关联,建立起数据结构,再把各个类依次加载生成对象,把指针交给解释器引用执行,而4.0.4解释器又有两种,C语言和汇编,移动和快速型;但虚拟机除了支持java语言以外,还支持c语言编写的程序,按照java接口进行调用,执行效率更高;当然使用JIT补丁的方法,会更便捷,加载更快,移植性较强,后面我们将介绍热加载的原理和常用的几种框架。

讲完dex文件,接下来可以讲讲安卓系统的启动过程,之前有过介绍,但本次希望以更通俗的语法来说明。系统按键触动驱动,触发init.rc的init进程启动,这是系统启动后的首个进程,再创建各种守护进程,然后启动Zygote进程,也就是用户进程,其他应用都是由它创建-fork子进程共享内存和资源,启动系统服务的SystemServer进程(相当于服务端)监听socket指令操作。x86初始化,执行dalvik/dalvikvm/Main.c中的main方法,执行JNI_CreateJavaVM函数创建虚拟机;而Arm平台初始化是从Zygote进程开始的,执行/jni/AndroidRuntime.cpp的startVm方法,通过JNI_CreateJavaVM函数创建虚拟机。然后调用startReg注册JNI函数,用来调用java类;调用ZygoteInit类的main方法:1、创建socket接口(相当于客户端),接收应用请求 2、调用预加载类和资源 3、启动SystemServer并分裂出sytem_server,启动各项系统服务,最终将线程加入Bind通信系统,此进程退出则Zygote退出重启4、调用runSelectLoopMode监听程序请求 注:子进程同样可以再fork出一个Zygote进程,所以在实际操作时,要区分一下。在子进程中fork函数返回0,在父进程返回负值 或此进程的pid,可以用来区别运行的是否是子进程或者创建成功与否。

虚拟机的功能可以分为以下几部分:

1、进程管理:每个虚拟机都有一个进程,依赖于Zygote机制实现

2、Zygote进程管理:会fork出来一个子Zygote进程,一个SystemServer进程,一个非Zygote进程的Speciallize进程

3、类加载:先加载所有类库,然后加载字节码,放入类数据结构,供类解释器执行,如果有关联的超类、接口等也一并加载

4、内存管理:使用新老生代结合的方式,使用复制+标记-清除的算法

4、本地接口:JNI

5、反射机制:通过类结构的加载,查看、调用、修改类中的方法和属性

6、解释器:负责执行Dex字节码

7、即时编译:JIT

Similar Posts:

  • Android虚拟机Dalvik Android的相关文件类型

    Android虚拟机Dalvik Dalvik冲击 随着Google 的AndroidSDK 的发布,关于它的API 以及在移动电话领域所带来的预期影响这些方面的讨论不胜枚举.不过,其中的一个话题在Java 社区是一石激起千层浪,这就是Android 平台的基础--Dalvik 虚拟机. Dalvik和标准Java虚拟机(JVM)首要差别 Dalvik 基于寄存器,而JVM 基于栈.,基于寄存器的虚拟机对于更大的程序来说,在它们编译的时候,花费的时间更短. Dalvik和Java运行环境的区别

  • java虚拟机和Dalvik虚拟机的区别,DVM为什么要设计成基于寄存器的!

    有人认为Dalvik虚拟机是一个Java虚拟机,因为Android的编程语言恰恰就是Java语言.但是这种说法并不准确,因为Dalvik虚拟机并不是按照Java虚拟机的规范来实现的,两者并不兼容:同时还要两个明显的不同: Java虚拟机运行的是Java字节码,而Dalvik虚拟机运行的则是其专有的文件格式DEX(Dalvik Executable). 在Java SE程序中的Java类会被编译成一个或者多个字节码文件(.class)然后打包到JAR文件,而后Java虚拟机会从相应的CLASS文件

  • JDK JRE Android SDk JVM Dalvik 关系 图解 源码框架分析

    写这篇文章主要解决以下几个问题: 1.为什么我配置了Android SDk 还要配置JDK呢?这两者到底是什么关系? 2.JVM是java程序的运行环境,  Dalvik 是android程序的运行环境,而android是用java语言编写的,那么 JVM 与Dalvik是什么关系呢? 3.为什么我下载的JDK有两个文件夹,一个是jdk,一个是jre.而jdk文件中其实已经包含了jre,为什么有两个呢? 4.为什么我不配置jdk的环境变量打不开eclipse,配置了之后,可以进入了,不过进入了e

  • 深入理解Android虚拟机二------虚拟机概述

    Java虚拟机: 1.Java虚拟机的数据类型: 2.Java虚拟机的体系结构: Java虚拟机结构框图 Android虚拟机-Dalvik VM Davlik VM架构 Android应用的编译和运行流程 Android的初始化流程

  • ubuntu创建android虚拟机之路

    最近迷上了ubuntu(64位),把能在win7上开发的事情,基本全部移到了ubuntu系统上,整体感觉比较爽,遇到问题解决问题,能够锻炼自己.今天,在ubuntu上安装的android sdk,把4.4.2那个版本也就是android19下载下来了,然后一些tool也下载了好了,然后就用eclipse(as还没有装好)准备测一个test,那首先得创建一个虚拟机吧,懒得用真机了,然后创建之后,碰到了第一个问题: 创建好之后,启动android虚拟机的时候,报如下错误: Failed to sta

  • android 虚拟机设置屏幕尺寸(800 * 480的)

    碰到这么问题是令我很郁闷的其实,因为我的笔记本是个14寸的,哎,屏幕小了点,我想让屏幕变成800 *480 的,在启动android虚拟机的时候,首先都知道是这么个界面, ,我选的是WVGA800(480*800),然后我就点Lauch了,这家伙,没想到,由于我的笔记本式14寸的,启动android虚拟机后,就感觉怪怪的,好像不是800*480的,呵呵, 结果用QQ截图,还真的不是啊.应该是等比例的缩小了,我还就是想看到800*480的效果呢,这样看来需要改改配置,于是回到刚刚的界面,这次点了一

  • Android虚拟机启用中文输入法及其它常用配置

    首先把语言设置为中文(简体): 设置(setting)->语言和输入法(Laguage&Input)->中文 首先点默认选中谷歌拼音输入法 然后点击下面谷歌输入法右边的选择按钮配置 然后打开浏览器 点击设置 设置主页 其它 设置搜索引擎为百度: 重启浏览器 注意shift+space切换输入法 多说一句:如果用VMware,切出虚拟机时要按Ctrl+Alter,这会导致虚拟机输入法出错,解决方法是在切回主机前把输入法换为英文 相关文章:VMware安装Android虚拟机

  • 【转载】ubuntu下给android虚拟机安装apk软件

    前段时间在window下做android开发,可以用adb命令给android虚拟机安装apk软件, 这段时间转到了linux下来,我用的是ubuntu,搭建好android开发环境的之后,我开始给 android虚拟机安装一些常用的软件,比如文件浏览器什么的. 首先打开终端,cd到android SDK所在的目录下,然后进入platform-tools文件夹,ls显示 文件后,你会发现有个名为adb的可执行文件,就是用这个adb命令来为android虚拟机安装 apk软件的. [plain]

  • Monkey入门之如何在android虚拟机中安装apk包

    如果想把公司的产品apk包安装到android虚拟机中,应该进行如下操作: 1.首先将apk包放到C:Program FilesAndroidandroid-sdkplatform-tools路径下(即SDK的platform-tools下): 2.win+R打开运行,执行cmd,在cd C:Program FilesAndroidandroid-sdkplatform-tools 注:为什么到C:Program FilesAndroidandroid-sdkplatform-tools下呢,因

  • Android虚拟机中添加sdcard

    Android虚拟机中添加sdcard 一 创建sdcard镜像文件: 1 打开cmd,进入到sdk所在盘,然后进入tools文件夹中,我的sdk放在E盘根目录下,所以我的完整路径是E:\sdk\tools,执行mksdcard命令就可以 2 mksdcard 256M android_sdcard中的256M代表sdcard的大小为256M,android_sdcard为sdcard镜像的文件名,运行途中的命令,即可在tools文件下生成一个Android_sccard的镜像文件. 3 创建A

Tags: