加载中…
个人资料
行者无疆-超越
行者无疆-超越
  • 博客等级:
  • 博客积分:0
  • 博客访问:23,180
  • 关注人气:1
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
正文 字体大小:

Android ART模式简介

(2014-04-23 19:05:15)
标签:

android

art

dalvik

虚拟机

it

分类: Android虚拟机
Android4.4最大的变化就是引入ART模式来代替Dalvik虚拟机。ART是Android Runtime的缩写,它提供了以AOT(Ahead-Of-Time)的方式运行Android应用程序的机制。所谓AOT是指在运行前就把中间代码静态编译成本地代码,这就节省了JIT运行时的转换时间。因此,和采用JIT的Dalvik相比,ART模式在总体性能有了很大的提升,应用程序不但运行效率更高,耗电量更低,而且占用的内存也更少
ART和dalvik相比,系统的性能得到了显著提升,同时占用的内存更少,因此能支持配置更低的设备。但是ART模式下编译出来的文件会比以前增大10%-20%,系统需要更多的存储空间,同时因为在安装时要执行编译,应用的安装时间也比以前更长了。


ART和dalvik相比,系统的性能得到了显著提升,同时占用的内存更少,因此能支持配置更低的设备。但是ART模式下编译出来的文件会比以前增大10%-20%,系统需要更多的存储空间,同时因为在安装时要执行编译,应用的安装时间也比以前更长了。

 

开启ART模式


在Android中ART模式缺省是关闭的,如果我们希望启动ART模式,需要在“设置”应用中手工打开它。进入“设置”后,选择“开发者选项”,再点击“选择运行环境”,会弹出如选择DALVIK或ART的对话框。选择ART后,系统将会重新启动,然后系统的运行环境就会从Dalvik切换到ART模式。
让我们打开“设置”应用的代码,看看这种切换到底做了些什么。下面是DevelopmentSettings.java中的一段代码:
    builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
             SystemProperties.set(SELECT_RUNTIME_PROPERTY, newRuntimeValue);
             pokeSystemProperties();
             PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
             pm.reboot(null);
         }
    });
上面这段代码只是设置重新设置了属性SELECT_RUNTIME_PROPERTY的值,然后就重启设备。这个属性的定义如下:
String SELECT_RUNTIME_PROPERTY = "persist.sys.dalvik.vm.lib"
注意属性是以persist开头的,所以它的值在重新开机后也可以保存。这个属性定义的是当前使用的运行环境库,如果是dalvik,它的值为libdvm.so,如果是art,它的值为libart.so。通过这个属性,系统就能判断出需要运行的模式。
ART系统的源码位于目录art下,包含了以下目录:
build目录:存放了一些mk文件。
compiler目录:动态库libart-compiler.so的源码目录,它包含了一个ART的编译器。
dalvikvm目录:可执行文件dalvikvm的源码目录。
dex2oat目录:可执行文件dex2oat的源码目录。用来将dex格式的文件编译成可执行文件。dex2oat文件会链接libart-compiler动态库。
jdwpspy目录:可执行文件jdwpspy的源码目录。这是一个调试工具,通过socket接收VM中输出的消息并打印输出。
oatdump目录:可执行文件oatdump的源码目录。这是一个工具,能dump出art文件的信息。
runtime目录:动态库libart.so的源码目录。
test目录:包含了大量测试代码的目录。
tools目录:包含了几个脚本文件。

 

两种模式的区别


从系统的实现角度看,ART和Dalvik的区别只表现在两个地方。一处是在安装应用执行优化时,Dalvik模式下执行的是dexopt程序,而ART模式下执行的是dex2oat程序。这个在“11.5.5节 dexopt(优化)命令”中已经介绍过来。通过dex2oat程序编译后得到的是elf格式的可执行文件,而不是以前的dalvik字节码了。
另一处是在运行应用时,Dalvik模式下系统为应用进程链接的是libdvm.so,而ART模式下链接的是libart.so。这两个库文件能够相互替换,是因为它们都实现了相同的接口。下面我们看看Android是如何来装载不同运行库的。
前面我们已经介绍过了,Zygote进程启动时会调用AndroidRuntime的start()函数来启动虚拟机,start()函数中有下面两行代码:
void AndroidRuntime::start(const char* className, const char* options)
{
    ......
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    ......
}
我们看看jni_invocation的Init()函数的代码:
bool JniInvocation::Init(const char* library) {
#ifdef HAVE_ANDROID_OS
  char default_library[PROPERTY_VALUE_MAX]; // 从property中得到运行库的名称
  property_get(kLibrarySystemProperty, default_library, kLibraryFallback);
#else
  const char* default_library = kLibraryFallback;
#endif
  if (library == NULL) {
    library = default_library;
  }
  handle_ = dlopen(library, RTLD_NOW); // 装载运行库
  if (handle_ == NULL) {
    ...... // 错误处理
  }
  // 装载三个VM的入口函数。
  if (!FindSymbol(reinterpret_cast(&JNI_GetDefaultJavaVMInitArgs_),
                  "JNI_GetDefaultJavaVMInitArgs")) {
    return false;
  }
  if (!FindSymbol(reinterpret_cast(&JNI_CreateJavaVM_),
                  "JNI_CreateJavaVM")) {
    return false;
  }
  if (!FindSymbol(reinterpret_cast(&JNI_GetCreatedJavaVMs_),
                  "JNI_GetCreatedJavaVMs")) {
    return false;
  }
  return true;
}
JniInvocation的Init()函数中通过属性persist.sys.dalvik.vm.lib取得了运行库的名称,然后调用dlopen()来装载运行库,同时从动态库中读取了三个函数的地址,它们是JNI_GetDefaultJavaVMInitArgs(),JNI_CreateJavaVM()和JNI_GetCreatedJavaVMs()。这三个函数相当于是虚拟机的三个入口函数,通过调用它们,就能创建出虚拟机系统。

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有