ART深入浅出1--虚拟机的启动和初始化
来源:互联网 发布:js filter函数 编辑:程序博客网 时间:2024/06/15 01:36
本文基于Android 7.1,不过因为从BSP拿到的版本略有区别,所以本文提到的源码未必与读者找到的源码完全一致。本文在提供源码片断时,将按照 <源码相对Android工程的路径>:<行号> <类名> <函数名> 的方式,如果行号对不上,请参考类名和函数名来找到对应的源码。
启动虚拟机
我们知道,Android的应用程序和服务都是由zygote进程产生的。zygote进程负责创建一个java虚拟机环境,并调用zygote的java入口。
zygote程序的主函数,放在文件frameworks/base/cmds/app_process/app_main.cpp中。通过简单阅读 main函数,我们发现,所有的工作被一个AppRuntime接管。AppRuntime类的核心函数 start启动了虚拟机并运行了指定的main函数。
frameworks/base/cmds/app_process/app_main.cpp:306 main
if (zygote) { runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } else if (className) {
runtime即AppRuntime。AppRuntime继承自AndroidRuntime,start函数也在AndroidRuntime中实现。
AndroidRuntime类在 frameworks/base/include/android_runtime/AndroidRuntime.h 中声明,在 frameworks/base/core/jni/AndroidRuntime.cpp中实现。
我们重点看下start函数的实现。AndroidRuntime::start调用了AndroidRuntime::startVm函数,启动虚拟机。startVm函数分成两部分:1. 准备参数;2. CreateJavaVM。
frameworks/base/core/jni/AndroidRuntime.cpp:948 AndroidRuntime::startVm
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { ALOGE("JNI_CreateJavaVM failed\n"); return -1; }
JNI_CreateJavaVM函数的原型是
libnativehelper/include/nativehelper/jni.h:1103
jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*);
参数initArgs的类型是JavaVMInitArgs,定义如下
libnativehelper/include/nativehelper/jni.h:1081
typedef struct JavaVMOption { const char* optionString; void* extraInfo;} JavaVMOption;typedef struct JavaVMInitArgs { jint version; /* use JNI_VERSION_1_2 or later */ jint nOptions; JavaVMOption* options; jboolean ignoreUnrecognized;} JavaVMInitArgs;
ART内的入口
现在我们终于进入了ART内部。ART内的JNI_CreateJavaVM函数,它的实现可以分为两部分:1. 初始化RuntimeOptions对象,保存参数;2. 启动Runtime。
Runtime在ART中代表一个java运行时环境。一个进程只有创建一个ART虚拟机,一个ART虚拟机只能有一个Runtime。下面看看JNI_CreateJavaVM函数的片断
art/runtime/java_vm_ext.cc:939 JNI_CreateJavaVM
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) { ScopedTrace trace(__FUNCTION__); const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args); if (IsBadJniVersion(args->version)) { LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version; return JNI_EVERSION; } RuntimeOptions options; 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; } ...//960 Runtime* runtime = Runtime::Current(); bool started = runtime->Start(); ...}
Runtime的创建和启动
Runtime::Create函数 (art/runtime/runtime.cc:486) 创建了Runtime实例,并调用它的Init方法。
Runtime::Init
Init方法做了很多事情,总结起来,有下面几个:
- 子模块的初始化,如MemMap::Init, 这是初始化内存映射模块; QuasiAtomic::Startup等。这一部分没有太多值得关注的;
- 设置关键变量,这些包括:
- boot_class_path_string_
- class_path_string_
- compiler_callbacks_ : 用来编译的后端对象
- compiler_executable_ :dex2oat的路径
- image_location_ : boot.art 等image的路径
- monitor_list_/monitor_pool_: 这是实现synchronized关键字的对象
- thread_list_: java的thread管理类
- intern_table_:字符串表
- 创建heap对象, heap_ = new gc::Heap(...)。heap创建过程中,会加载image。
- 创建自己的信号处理函数,InitPlatformSignalHandlers()。对于一些运行时异常,如NullPointerException, StackOverflowExeption等,ART都是通过linux信号机制实现的额。例如,ART截取SIGSEGV信号,如果发现这是一个空指针问题,且发生空指针的代码处于java代码中,它就会产生一个NullPointerException抛出,然后继续运行程序。
- 创建ClassLinker对象。这是一个非常重要的对象,类的加载、链接和初始化都是在这个类中完成的。
Runtime::Init其实做了非常多的事情。本小结内很难一一解释。我们将在后面介绍各个子单元的时候,都会详细介绍它们的初始化过程。
Runtime::Start
如果说Runtime::Init是初始化虚拟机的,那么,Runtime::Start就是为运行java代码做准备的。
这个函数不大,但是做了非常多的事情,下面我也将其中关键代码列出
art/runtime/runtime.cc:566
bool Runtime::Start() { ....//585 // Create the JIT either if we have to use JIT compilation or save profiling info. // TODO(calin): We use the JIT class as a proxy for JIT compilation and for // recoding profiles. Maybe we should consider changing the name to be more clear it's // not only about compiling. b/28295073. if (jit_options_->UseJitCompilation() || jit_options_->GetSaveProfilingInfo()) { std::string error_msg; if (!IsZygote()) { // If we are the zygote then we need to wait until after forking to create the code cache // due to SELinux restrictions on r/w/x memory regions. CreateJit(); } else if (jit_options_->UseJitCompilation()) { if (!jit::Jit::LoadCompilerLibrary(&error_msg)) { // Try to load compiler pre zygote to reduce PSS. b/27744947 LOG(WARNING) << "Failed to load JIT compiler with error " << error_msg; } } } if (!IsImageDex2OatEnabled() || !GetHeap()->HasBootImageSpace()) { ScopedObjectAccess soa(self); StackHandleScope<2> hs(soa.Self()); auto class_class(hs.NewHandle<mirror::Class>(mirror::Class::GetJavaLangClass())); auto field_class(hs.NewHandle<mirror::Class>(mirror::Field::StaticClass())); class_linker_->EnsureInitialized(soa.Self(), class_class, true, true); // Field class is needed for register_java_net_InetAddress in libcore, b/28153851. class_linker_->EnsureInitialized(soa.Self(), field_class, true, true); } // InitNativeMethods needs to be after started_ so that the classes // it touches will have methods linked to the oat file if necessary. { ScopedTrace trace2("InitNativeMethods"); InitNativeMethods(); } // Initialize well known thread group values that may be accessed threads while attaching. InitThreadGroups(self); Thread::FinishStartup(); system_class_loader_ = CreateSystemClassLoader(this); if (is_zygote_) { if (!InitZygote()) { return false; } } else { ....//644 } StartDaemonThreads(); ....}
重点的初始化有:
- CreateJit : 从Android 6.0开始引入JIT(Just In Time) ,在7.0中开始大规模使用;
- 初始化基本类 class_class ,即java.lang.Class类,这是最基础的类;
- InitNativeMethods(): 将java.lang下面最基础的类的JNI接口进行初始化;
- InitZygote:这是zygote程序在调用时,需要做的事情。app_main.cpp文件不仅是zygote的主程序,也是安卓的am命令行的主程序,故此这里做了区分;
- StartDemonThreads,调用java.lang.Daemons.start,启动一组线程,它们的作用是,执行GC、调用finalize方法、 处理ReferenceQueue等一系列工作。
这里面需要注意的是:只有zygote和am程序会调用JNI_CreateJavaVM函数,被zygote孵化出的其他进程都不再执行这个入口函数,而是转而执行Runtime::PreZygoteFork和Runtime::InitNonZygoteOrPostFork。这一点将在后面,专门介绍ART是如何支持zygote孵化子进程的。
阅读全文
0 0
- ART深入浅出1--虚拟机的启动和初始化
- Android ART 的初始化和启动
- Art 虚拟机的启动
- 深入理解ART虚拟机—虚拟机的启动
- Dalvik和ART虚拟机的区别
- ART 和 Dalvik 虚拟机
- art虚拟机启动过程分析
- Dalvik虚拟机和Art虚拟机
- ART深入浅出3--了解Boot.art和boot-*.art
- JVM、Dalvik VM和ART虚拟机之间的区别
- Art和Dalvik对比以及虚拟机的原理
- JVM、Dalvik VM和ART虚拟机之间的区别
- Dalvik虚拟机和ART(Android RunTime)的区别
- Android Dalvik虚拟机和ART虚拟机对比
- 深入浅出Java类和对象的初始化
- Android的新虚拟机ART
- JAVA虚拟机、Dalvik虚拟机和ART虚拟机简要对比
- JAVA虚拟机、Dalvik虚拟机和ART虚拟机简要对比
- Lucene(2)搜索
- python中numpy的用法总结
- c++函数重载的实现原理
- 推荐系统学习-LibMF
- hive 的介绍和安装
- ART深入浅出1--虚拟机的启动和初始化
- 项目管理-PMP-第8章 人力资源管理
- 推荐系统学习-SVDFeature
- RUP的最佳实践
- Oracle查询当前某条数据的前一行数据与后一行数据
- 【量亿数据-金融数据】如何进行套息交易
- conda 环境管理
- 图像绘制与离屏渲染
- RabbitMQ publisher customer with confirm ack and customertag