欢迎来真孝善网,为您提供真孝善正能量书籍故事!

Android虚拟机技术:Dalvik、ART与ODEX的协同进化

时间:11-03 民间故事 提交错误

大家好,今天来为大家分享Android虚拟机技术:Dalvik、ART与ODEX的协同进化的一些知识点,和的问题解析,大家要是都明白,那么可以忽略,如果不太清楚的话可以看看本篇文章,相信很大概率可以解决您的问题,接下来我们就一起来看看吧!

如果你“懒”,懒得看老罗的源码分析,长篇大论

请阅读以下“简述”内容

一:Dalvik和ART的区别#

Dalvik:Dalvik是Google自己为Android平台设计的Java虚拟机。它可以支持已转换为.dex(即Dalvik Executable)格式的Java应用程序的运行。dex 格式是专为Dalvik 设计的。一种适合内存和处理器速度有限的系统的压缩格式。执行的是字节码,依靠Just-In-Time(JIT)机制来解释字节码

ART:Android Runtime,由Google专门为Android开发,用于取代Dalvik。 Android KK面向开发者推出,L版本正式上线。它比替代方案更高效、更省电,它执行本地机器代码(即Linux 的ELF 文件格式)并依赖于Ahead-Of-Time (AOT) 机制。

二.在不同平台DEX转化为ODEX的过程#

简化流程如下:

打包安装运行的简化流程.png 这里参考的是

http://blog.csdn.net/luoshengyang/article/details/18006645

android安装过程源码分析:http://blog.csdn.net/luoshengyang/article/details/6747696

简单来说,Android系统通过PackageManagerService来安装APK。在安装过程中,PackageManagerService会通过另一个类Installer的成员函数dexopt对APK中的dex字节码进行优化:

公共最终类安装程序{

.

公共int dexopt(String apkPath, int uid, boolean isPublic) {

StringBuilder 构建器=new StringBuilder("dexopt");

生成器.append(" ");

生成器.append(apkPath);

生成器.append(" ");

生成器.append(uid);

builder.append(isPublic ? " 1" : " 0");

返回执行(builder.toString());

}

.

}该函数定义在文件frameworks/base/services/java/com/android/server/pm/Installer.java中。安装程序通过套接字向守护进程installd 发送dexopt 请求。该请求由installd中的函数dexopt处理。详细流程请参见Android ART运行时无缝替换Dalvik虚拟机的流程分析。

int dexopt(const char *apk_path, uid_t uid, int is_public)

{

结构utimbuf ut;

struct stat apk_stat, dex_stat;

char out_path[PKG_PATH_MAX];

char dexopt_flags[PROPERTY_VALUE_MAX];

char persist_sys_dalvik_vm_lib[PROPERTY_VALUE_MAX];

字符*结束;

int res, zip_fd=-1, out_fd=-1;

.

/* 要运行的命令取决于persist.sys.dalvik.vm.lib 的值*/

property_get("persist.sys.dalvik.vm.lib", persist_sys_dalvik_vm_lib, "libdvm.so");

/* 首先: 是否有.odex 文件?如果是这样,我们有

* 预编译了apk,这里没有什么可做的。

*/

sprintf(out_path, "%s%s", apk_path, ".odex");

if (stat(out_path, dex_stat)==0) {

返回0;

}

如果(create_cache_path(out_path,apk_path)){

返回-1;

}

.

out_fd=open(out_path, O_RDWR | O_CREAT | O_EXCL, 0644);

.

pid_t 进程号;

pid=fork();

如果(pid==0){

.

if (strncmp(persist_sys_dalvik_vm_lib, "libdvm", 6)==0) {

run_dexopt(zip_fd, out_fd, apk_path, out_path, dexopt_flags);

} 否则if (strncmp(persist_sys_dalvik_vm_lib, "libart", 6)==0) {

run_dex2oat(zip_fd, out_fd, apk_path, out_path, dexopt_flags);

} 别的{

退出(69); /* 意外的persist.sys.dalvik.vm.lib 值*/

}

退出(68); /* 仅在执行失败时到达这里*/

}

.

}

……

static void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name,

const char* 输出文件名、const char* dexopt_flags)

{

static const char* DEX_OPT_BIN="/system/bin/dexopt";

静态常量int MAX_INT_LEN=12; //"-"+10dig+"" -OR-0x+8dig

字符zip_num[MAX_INT_LEN];

char odex_num[MAX_INT_LEN];

sprintf(zip_num, "%d", zip_fd);

sprintf(odex_num, "%d", odex_fd);

ALOGV("运行%s in=%s out=%sn", DEX_OPT_BIN, 输入文件名, 输出文件名);

execl(DEX_OPT_BIN, DEX_OPT_BIN, "--zip", zip_num, odex_num, input_file_name,

dexopt_flags, (char*) NULL);

ALOGE("execl(%s) failed: %sn", DEX_OPT_BIN, strerror(errno));

}

static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,

const char* 输出文件名、const char* dexopt_flags)

{

静态const char* DEX2OAT_BIN="/system/bin/dex2oat";

静态常量int MAX_INT_LEN=12; //"-"+10dig+"" -OR-0x+8dig

char zip_fd_arg[strlen("--zip-fd=") + MAX_INT_LEN];

char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX];

char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN];

char oat_location_arg[strlen("--oat-name=") + PKG_PATH_MAX];

sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);

sprintf(zip_location_arg, "--zip-location=%s", input_file_name);

sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);

sprintf(oat_location_arg, "--oat-location=%s", 输出文件名);

ALOGV("运行%s in=%s out=%sn", DEX2OAT_BIN, input_file_name, output_file_name);

execl(DEX2OAT_BIN,DEX2OAT_BIN,

zip_fd_arg、zip_location_arg、

燕麦_fd_arg,燕麦_位置_arg,

(字符*)空);

ALOGE("execl(%s) failed: %sn", DEX2OAT_BIN, strerror(errno));

}该函数定义在frameworks/native/cmds/installd/commands.c中。函数dexopt首先读取系统属性persist.sys.dalvik.vm.lib的值,然后在/data/dalvik-cache目录中创建odex文件。该odex文件是优化为dex文件的输出文件。接下来,函数dexopt通过fork创建一个子进程。如果系统属性persist.sys.dalvik.vm.lib的值等于libdvm.so,那么子进程将调用函数run_dexopt将dex文件优化为odex文件。另一方面,如果系统属性persist.sys.dalvik.vm.lib的值等于libart.so,那么子进程会调用函数run_dex2oat将dex文件翻译成oat文件,这实际上是翻译dex字节码生成本地机器代码并将其保存在oat文件中。

函数run_dexopt通过调用/system/bin/dexopt优化dex字节码,函数run_dex2oat通过调用/system/bin/dex2oat将dex字节码翻译为本地机器码。注意,无论是优化dex字节码还是将dex字节码翻译成本地机器码,最终的结果都是保存在同名的odex文件中,但前者对应的是一个dey文件(表明这是一个优化后的dex),它对应于一个oat文件(实际上是一个自定义的elf文件,其中包含本地机器指令)。这样,任何通过绝对路径引用odex文件的代码都不需要修改。

三.oat文件格式#

借助罗大神的图,我们可以知道OAT文件本质上是一个ELF文件,所以在最外层它具有一般ELF文件的结构。例如,它有一个标准的ELF文件头,并由Section描述。文件内容。

粘贴_图像.png

OAT 文件包含两个特殊部分:oatdata 和oatexec。前者包含用于生成本地机器指令的dex文件的内容,后者包含生成的本地机器指令。它们之间的关系是通过存储在oatdata 部分前面的oat header 来实现的。部门描述。

APK安装过程中生成的OAT文件的输入只有一个DEX文件,该DEX文件来自于待安装的APK文件中打包的classes.dex文件。事实上,一个OAT文件可以由多个DEX生成。这意味着生成的OAT文件的oatdata部分包含多个DEX文件。详细分析请转至Android运行时ART加载OAT文件的过程分析。

四.multidex加载odex,multidex和oat的关系

MultiDex在dalvik虚拟机上的简要安装过程:

将/data/app/apkName.apk路径解压得到的classes2.dex,classesN.dex写入/data/data/pkgName/code_cache/secondary-dexes/apkName.apk.classes2.zip等zip按顺序。文件的classes.dex并返回此zip列表。然后执行该zip 列表的安装过程。具体过程是将要安装的zip列表添加到BaseDexClassLoader的pathList实例的dexElements数组中,其中会对每个dex文件进行dex2opt优化。一旦添加到dexElements数组中,ClassLoader就会在程序启动时加载dexElements数组中的元素,从而实现多dex安装。

上面提到,OAT文件可以由多个dex生成,即安装时不需要multidex,但是multidex包含在应用程序中。

安装和虚拟机关系不大。

@覆盖

受保护的无效attachBaseContext(上下文基础){

super.attachBaseContext(base);

MultiDex.install(this);

}在install函数中,在提取dex文件列表之前会进行一些验证操作,包括检查APK是否已经安装。如果APK已经安装,则不再进行后续操作。检查SDK版本号。如果版本号大于20,并不能保证MultiDex能够正常工作。

设置var2=已安装的Apk;

同步(已安装的Apk){

字符串apkPath=e.sourceDir;

if(installedApk.contains(apkPath)) {

返回;

}所以multidex不会影响ART上程序的逻辑,与ART无关~。

multidex源码分析:MultiDex安装过程源码分析

小结:

从安装过程

Java代码实际上需要两次“转换”才能在Android设备上运行

1.PC端:class-.dex-.apk

2.phone:dex-odex

区别在于第二步。

ART :dex-.odex(机器代码)(AOTAhead-Of-Time)

Dalvik:dex-.odex(字节码)(JIT | 即时)

机器码可以直接执行,而字节码需要每次启动时执行,将优化后的odex字节码转换为机器码。

ART优缺####

系统性能大幅提升

应用程序启动和运行速度更快

减少每次启动时的编译以延长电池寿命

存储占用较大

安装时间较长

复制粘贴+明白了,希望忘记了可以回来看看~!

关于本次Android虚拟机技术:Dalvik、ART与ODEX的协同进化和的问题分享到这里就结束了,如果解决了您的问题,我们非常高兴。

用户评论

青山暮雪

我终于明白 Dalvik 和 ART 是 Android 系统中运行 Apps 的两种关键引擎了!

    有8位网友表示赞同!

幸好是你

ODEX 可以让应用启动更快, 这对用户体验真的太重要啦。

    有13位网友表示赞同!

灬一抹丶苍白

想深入了解 Android 原理,肯定要搞清楚 Dalvik, ART 和 ODEX 的关系呀!

    有10位网友表示赞同!

暖栀

以前没听过这些词儿,看来得花时间学习了!

    有13位网友表示赞同!

_心抽搐到严重畸形っ°

Dalvik 是老版本,ART 更新更强大吗? 这两者有何区别呢?

    有9位网友表示赞同!

颓废i

ODEX 做了什么作用呢? 简直是手机性能的利器啊!

    有8位网友表示赞同!

服从

这三种技术都与我日常的手机使用息息相关, 真是不得不佩服Android工程师的设计能力!

    有18位网友表示赞同!

念初

学习他们的设计理念一定能对软件工程有所启发!

    有13位网友表示赞同!

优雅的叶子

如果想开发 Android 应用,这些知识是必不可少的吧?

    有18位网友表示赞同!

有恃无恐

这篇文章应该会让我对Android的底层逻辑有更深的理解。

    有19位网友表示赞同!

权诈

感觉技术总是迭代升级的, Dalvik 到 ART 就像手机升级一样!

    有16位网友表示赞同!

她最好i

"相爱相生" 这句话很有意思,体现了它们之间的关联性!

    有5位网友表示赞同!

在哪跌倒こ就在哪躺下

期待了解更多关于这些技术背后的故事和应用场景。

    有12位网友表示赞同!

面瘫脸

原来手机后台运行的这么多复杂的操作,真是让人佩服!

    有12位网友表示赞同!

■□丶一切都无所谓

这篇文章让我对 Android 的底层结构有了更清晰的认知。

    有12位网友表示赞同!

墨染天下

这种深入浅出的讲解方式真的很棒!

    有14位网友表示赞同!

伪心

学习这种技术知识真不容易,需要不断探索和实践。

    有19位网友表示赞同!

陌離

希望可以将这些理论知识应用到实际项目中!

    有16位网友表示赞同!

【Android虚拟机技术:Dalvik、ART与ODEX的协同进化】相关文章:

1.蛤蟆讨媳妇【哈尼族民间故事】

2.米颠拜石

3.王羲之临池学书

4.清代敢于创新的“浓墨宰相”——刘墉

5.“巧取豪夺”的由来--米芾逸事

6.荒唐洁癖 惜砚如身(米芾逸事)

7.拜石为兄--米芾逸事

8.郑板桥轶事十则

9.王献之被公主抢亲后的悲惨人生

10.史上真实张三丰:在棺材中竟神奇复活