Android ART 的初始化和启动

ART的初始化

下面我们从JNI_GetDefaultJavaVMInitArgs(),JNI_CreateJavaVM()和JNI_GetCreatedJavaVMs()三个函数入手来了解ART的初始化过程。这三个函数的代码位于jni_internal.cc中。

JNI_GetDefaultJavaVMInitArgs()函数在ART中没有作为,只是返回JNI_ERR。如下所示:

extern "C" jintJNI_GetDefaultJavaVMInitArgs(void* ) {

return JNI_ERR;

}

JNI_GetCreatedJavaVMs()函数用来返回在Runtime中保存的JavaVMExt的指针,函数代码如下所示:

extern "C" jint JNI_GetCreatedJavaVMs(JavaVM**vms, jsize, jsize* vm_count) {

Runtime* runtime =Runtime::Current();

if (runtime == NULL) {

*vm_count = 0;

} else {

*vm_count = 1;

vms[0] = runtime->GetJavaVM();

}

return JNI_OK;

}

Runtime的GetJavaVM()函数只是返回了Runtime类的成员变量java_vm_,如下所示。

JavaVMExt* GetJavaVM() const {

return java_vm_;

}

java_vm_是JavaVMExt类型的指针,定义如下:

JavaVMExt* java_vm_;

理解了两个简单的函数后,我们再来分析JNI_CreateJavaVM()函数,代码如下:

extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm,JNIEnv** p_env, void* vm_args) {

const JavaVMInitArgs* args =static_cast(vm_args);

// 检查JNI的版本

if(IsBadJniVersion(args->version)) {

LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: "<< args->version;

return JNI_EVERSION;

}

// 保存启动参数到options中。

Runtime::Optionsoptions;

for (int i = 0; i <args->nOptions; ++i) {

JavaVMOption* option = &args->options[i];

options.push_back(std::make_pair(std::string(option->optionString),option->extraInfo));

}

bool ignore_unrecognized =args->ignoreUnrecognized;

if (!Runtime::Create(options,ignore_unrecognized)) { // 创建虚拟机

return JNI_ERR;

}

Runtime* runtime =Runtime::Current();

bool started =runtime->Start();      //启动虚拟机

if (!started) {

delete Thread::Current()->GetJniEnv();

delete runtime->GetJavaVM();

return JNI_ERR; // 启动失败,方法

}

*p_env =Thread::Current()->GetJniEnv();

*p_vm =runtime->GetJavaVM();

return JNI_OK;

}

JNI_CreateJavaVM()函数中调用Runtime的Create()函数来创建虚拟机,然后调用start()函数来启动它。在ART中,Runtime对象的地位和Dalvik中的DvmGlobals对象gDVm类似,包含了所有重要的变量。

下面我们继续分析Create()函数:

bool Runtime::Create(const Options& options,bool ignore_unrecognized) {

if (Runtime::instance_ !=NULL) {

return false;  //只能创建一个Runtime实例

}

InitLogging(NULL);  // Calls Locks::Init() as aside effect.

instance_ = newRuntime;  // 创建了Runtime类的实例

if(!instance_->Init(options, ignore_unrecognized)){ // 初始化Runtime对象

delete instance_;

instance_ = NULL;

return false;

}

return true;

}

Runtime的Create()函数中创建了Runtime对象,并调用它的Init()函数进行初始化。函数代码如下:

bool Runtime::Init(const Options&raw_options, bool ignore_unrecognized) {

UniquePtroptions(ParsedOptions::Create(raw_options,

ignore_unrecognized));

......

QuasiAtomic::Startup();

Monitor::Init(options->lock_profiling_threshold_,

options->hook_is_sensitive_thread_);

host_prefix_ =options->host_prefix_;

boot_class_path_string_ =options->boot_class_path_string_;

... // 更多的赋值语句

monitor_list_ = newMonitorList;

thread_list_ = newThreadList;

intern_table_ = newInternTable;

if(options->interpreter_only_) {

GetInstrumentation()->ForceInterpretOnly();

}

// 创建堆(Heap)对象

heap_ = newgc::Heap(options->heap_initial_size_,

options->heap_growth_limit_,

......);

BlockSignals();

InitPlatformSignalHandlers();

// 创建JavaVMExt对象

java_vm_ = new JavaVMExt(this,options.get());

// 将当前的主线程变成一个“Java” 线程

Thread::Startup();

Thread* self =Thread::Attach("main", false, NULL, false);

self->TransitionFromSuspendedToRunnable();

GetHeap()->EnableObjectValidation();

if(GetHeap()->GetContinuousSpaces()[0]->IsImageSpace()) {

class_linker_ = ClassLinker::CreateFromImage(intern_table_);

} else {

class_linker_ =ClassLinker::CreateFromCompiler(*options->boot_class_path_, intern_table_);

}

......

return true;

}

Init()函数最重要的工作是创建了Heap对象和ClassLinker对象。我们只要将ART和Dalvik对比一下就可以理解,因为ART模式下并不需要去解析和执行字节码,所以它的工作比Dalivk要少很多。即使应用已经编译成了可执行代码,但是同样也要支持垃圾回收功能,所以Heap模块还是必不可少的。Art的Heap模块的功能几乎和Dalvik中的相同,垃圾回收的算法也是标志并清除法,不过代码的实现更加晦涩,所以本书不打算再分析一遍Art的Heap算法了。

ART虽然不用去装载和执行字节码,但是还是要保留所有Java类的信息,Java程序和C++程序除了内存管理方式不同外,最大的区别是Java程序能够动态的获取各种类的信息,包括方法,变量等。所以ART中同样也要提供这些功能,否则编译出来的程序也无法使用。ClassLinker类的作用就是在ART内部提供各种Java类的解析功能。

ART开始运行

初始化完成之后,接下来是调用Runtime的start()函数开始运行,函数代码如下:

bool Runtime::Start() {

VLOG(startup) <<"Runtime::Start entering";

Thread* self =Thread::Current();

self->TransitionFromRunnableToSuspended(kNative);

started_ = true;

InitNativeMethods()   //初始化本地的JNI方法

InitThreadGroups(self);

Thread::FinishStartup();

if (is_zygote_) {

if (!InitZygote()) {

return false;

}

} else {

DidForkFromZygote();

}

StartDaemonThreads();  //调用java.lang.Daemons的start方法

system_class_loader_ =CreateSystemClassLoader(); //创建一个ClassLoader对象

self->GetJniEnv()->locals.AssertEmpty();

VLOG(startup) <<"Runtime::Start exiting";

finished_starting_ =true;

return true;

}

Start()方法中会调用InitNativeMethods()来初始化本地的JNI方法,ART中也同样支持JNI函数,不过ART中对部分系统的JNI函数进行了重写,但是实现原理和Dalvik中的没有太大区别,而大部分其他模块的JNI函数还是保持不变。调用InitNativeMethods()方法后这些JNI函数就可以使用了。

接下来如果是在Zygote进程中,则会调用InitZygote()函数来进行初始化,这个函数的实现和Dalvik中的几乎一样,主要工作是设置进程的groupid,以及mountrootfs文件系统到根目录。如果不是Zygote进程,则调用DidForkFromZygote()函数,这个函数主要工作是调用Heap对象的CreateThreadPool()函数来创建线程池。

最后Start()函数中调用了StartDaemonThreads()函数,这个函数的工作是调用Java类Daemons的start()方法来启动一些Deamon线程,这些Deamon前面我们已经分析过了。这个过程实际上和Dalvik启动时完成的最后一项工作相同。

对比Dalivk启动时需要完成的工作,ART是相当的简单了。

Android ART 的初始化和启动,码迷,mamicode.com

时间: 2024-08-06 04:15:18

Android ART 的初始化和启动的相关文章

Android Art Hook 技术方案

Android Art Hook 技术方案 by 低端码农 at 2015.4.13 www.im-boy.net 0x1 开始 Anddroid上的ART从5.0之后变成默认的选择,可见ART的重要性,目前关于Dalvik Hook方面研究的文章很多,但我在网上却找不到关于ART Hook相关的文章,甚至连鼎鼎大名的XPosed和Cydia Substrate到目前为止也不支持ART的Hook.当然我相信,技术方案他们肯定是的,估计卡在机型适配上的了. 既然网上找不到相关的资料,于是我决定自己

Android漫游记(6)---APP启动之旅(I)

Android基于Linux2.6+内核,我们看一张图,以对Android系统的架构有个感性的认识. 我们从Kernel层简单说明: 1.Kernel层:基于Linux2.6+内核,同时做了一些嵌入式环境做了一些针对性的优化调整. 2.Libraries层:包括Bionic C库,以及HAL(硬件驱动接口抽象)等API. 3.Android Runtime(ART)层:包含核心应用库和Dalvik虚拟机. 4.Application Framework层:纯JAVA的API框架,包括Activi

Android ART运行时与Dalvik虚拟机

这几天在做一个项目时需要在Android中使用OSGi框架(Apache Felix),于是在一个android 4.4.2 版本系统的某品牌的平板上实验. 实验内容很简单:把felix包里的felix.jar包和一些bundles的jar包用android sdk里的dx及aapt工具转化为包含dex字节码的jar 包.这样使这些jar包能在Android上跑起来.(因为Android上使用的是在Dalvik虚拟机而不是标准的java虚拟机,所以“原生”的 jar包不能直接在Android上跑

Android -- Audio Native服务之启动流程分析(一)

Android -- Audio Native服务之启动流程分析(一) Android中的Audio系统是比较庞大.繁杂的一部分内容, 其中会涉及较多的音频编解码.多媒体制式与Android Audio HAL设备管理的知识.随着Android的发展,其所支持的音频设备也变得越来丰富,如扬声器.耳机.听筒等等:这种变化也为Android管理如此丰富的音频设备以及如何正确.合理地切换音频输出提出了更高的要求.面对如此繁杂的管理要求,我们分析Android Audio服务的历程想必也不会轻松.接下来

ReactNative入门之android与rn初始化参数的传递

1.基本理念 RN APP本质上也是原生APP,只是在原生APP中加入了React Native视图的支持.因此获取RN APP的启动参数的方法原生APP是一样的,获取启动参数后再通过合适的方法传递给RN视图.如何获得启动参数,不要再搜索RN如何获得启动参数,直接参考原生APP获得启动参数的文章.可以参考这个例子:ndroid中一个APP启动另一个APP并传递参数 本文重点说明如何将启动参数传递给React Native代码. 2.ReactNative的Ativity继承关系 MainActi

Android Studio初体验之启动AVD模拟器异常:cannot set up guest memory &#39;pc.ram&#39;

启动AVD模拟器异常:Cannot set up guest memory 'pc.ram' 错误信息: HAX is working and emulator runs in fast virt mode Cannot set up guest memory 'pc.ram': Invalid argument Error accepting connect 分析 各种查资料,没有发现网上有同样问题的,在一篇相关文章中找到类似的解决方法. 从语意看,应该是hax安装后没有启动.(不懂hax是什

Android——判断Service是否已经启动

延续百度地图定位的Demo,采用Service来进行百度定位,并且将数据上传到服务器上遇到了一个问题:在真机中使用清理内存来关闭程序的之后,Service会被关闭,但是过几秒中,它又会自动重启:重启就算了,而且再次登陆系统的时候,又会开启一个一样的服务,在LogCat中就会看到每次都获取到两次的定位数据.然后想想是否可以在建立Service之前判断这个服务有没有被创建?只要能做这个判断,那么服务存在我们就不管它,如果不存在则创建,本着这个思路,百度发现可行(Service后台服务创建时最好都要判

Android开发问题之无法启动虚拟机

问题分析: [2014-01-16 20:18:26 - ] The connection to adb is down, and a severe error has occured. [2014-01-16 20:18:26 - ] You must restart adb and Eclipse. [2014-01-16 20:18:26 - ] Please ensure that adb is correctly located at 'E:\java\sdk\platform-too

Curator源码解析(二)初始化和启动分析

上一篇文章这里已经列出了Curator的一个使用的例子,这篇文章将详细分析其初始化和启动部分. 测试程序分析 1      初始化和启动 (1) newClient方法返回CuratorFramework接口对象: public staticCuratorFramework newClient(String connectString, int sessionTimeoutMs,int connectionTimeoutMs,RetryPolicy retryPolicy) { return b