AOSP 8.0 系统启动之四ART虚拟机启动(一)

您所在的位置:网站首页 安卓基于java虚拟机怎么用 AOSP 8.0 系统启动之四ART虚拟机启动(一)

AOSP 8.0 系统启动之四ART虚拟机启动(一)

#AOSP 8.0 系统启动之四ART虚拟机启动(一)| 来源: 网络整理| 查看: 265

目录

前言

一、创建虚拟机

1.1 JniInvocation.Init

1.2 startVm

1.2.1 JNI_CreateJavaVM

1.2.2 Runtime::Create

1.2.3 Runtime::Init

1.2.4 JavaVMExt::Create

1.2.4 Thread::Startup

1.2.5 Thread::Attach

1.2.6 Thread::Init​​​​​​​

1.2.7 JNIEnvExt::Create

1.2.8 ::art::SetThreadName

1.2.9 Runtime::Start

1.2.10 Thread::FinishStartup

1.2.11 Thread::CreatePeer

二、小结

前言

Dalvik虚拟机和ART虚拟机

Dalvik虚拟机,基于apache的JVM 改进而来,为Android 第一代虚拟机。在Android 4.4之前使用。ART 虚拟机,也叫ART 模式,是第二代虚拟机,Android 4.4推出,并从5.0开始默认使用执行程序。

两者区别:

Dalvik每次都要将apk代码编译成机器码再运行,Art只会首次启动编译,而不必每次运行都要先编译一次。Art占用空间比Dalvik大,首次安装Apk的时间比Dalvk模式长Art减少编译,减少了CPU使用频率,使用明显改善电池续航;应用启动更快、运行更快、体验更流畅、触感反馈更及时

重点说下art虚拟机:

当然无论是 Dalvik 还是 Art,或者未来可能出现的新型虚拟机,它们提供的功能将全部封装在一个 so 库中,并且对外需要暴露 JNI_GetDefaultVMInitArgs、JNI_CreateVM 和 JNI_GetCreatedJavaVMs 三个标准接口,使用者(比如 Zygote)只需要按照统一的接口标准就可以控制和使用所有同类型的虚拟机了。

组成 Android 虚拟机的核心自系统包括但不限于 Runtime、ClassLoader System、Execution、Engine System、Heap Manager 和 GC 系统、JIT、JNI 环境等。

和标准的 JVM 一样,类加载器在 Android 虚拟机中也扮演者很重要的作用,可以分为 Boot ClassLoader、System ClassLoader、Dex ClassLoader 等,所有被加载的类和它们的组成元素都将由 ClassLinker 做统一的管理。

除了字节码解释执行的方式,Art 还支持通过 AOT 来直接执行字节码编译而成的机器码。

AOT 的编译时机有两个:

随 Android ROM 构建时一起编译。程序安装时执行编译(针对第三方应用程序)。

Art 引入了新的存储格式,即 OAT 文件来存储编译后的机器代码。而 OAT 机器码的加载需要用到 ELF 的基础能力。

另外,由于一股脑地在程序安装阶段将 Dex 转化为 OAT 造成造成了一定的资源浪费,从 Android N 版本开始,Art 又改变了之前的 OAT 策略——程序在安装时不再统一执行 dex2oat,而改由根据程序的实际运行情况来决定有哪些部分需要被编译成本地代码,即恢复了 Interpreter、JIT、OAT 三足鼎立的局面。一方面,这种新变化大幅加快了程序的安装速度,解决了系统更新时用户需要经历漫长等待的问题;另一方面,由于程序的首次启动必须通过解释器来运行,Android N 版本必须采用多种手段(新的解释器,将 Verification 前移等)来保证程序的启动速度不受影响。

应用程序除了解释执行外,还会在运行过程中实时做 JIT 编译——不过它的结果并不会被持久化。另外,虚拟机会记录下应用程序在动态运行过程中被执行过的函数,并输出到 Profile 文件里。

AOT compile daemon 将在系统同时满足 idle 和充电状态两个条件时才会被唤醒,并按照一定的逻辑来遍历执行应用程序的 AOT 优化。由于参与 AOT 的函数数量通常只占应用程序代码的一小部分,所以整体而言 Android N 版本 AOT 结果所占用的空间大小比旧版本要小很多。

本文涉及源码

platform/frameworks/base/cmds/app_process/app_main.cpp platform/frameworks/base/core/jni/AndroidRuntime.cpp platform/libnativehelper/JniInvocation.cpp 一、创建虚拟机

platform/frameworks/base/core/jni/AndroidRuntime.cpp

// app_main.cpp main(){ AppRuntime runtime; runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } // class AppRuntime : public AndroidRuntime // AppRuntime继承AndroidRuntime // AndroidRuntime.cpp void AndroidRuntime::start(const char* className, const Vector& options, bool zygote){ //第一步:开始虚拟机 if (startVm(&mJavaVM, &env, zygote) != 0) { return; } //第二步:注册系统jni if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } //第三步:进入zygoteinit.java main方法 startClass = com.android.internal.os.ZygoteInit jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([L; } //先重点分析第一步 void AndroidRuntime::start(const char* className, const Vector& options, bool zygote) {     ... //打印一些日志,获取ANDROID_ROOT环境变量     /* start the virtual machine */     JniInvocation jni_invocation;     jni_invocation.Init(NULL);//初始化JNI,加载libart.so     JNIEnv* env;     if (startVm(&mJavaVM, &env, zygote) != 0) {//创建虚拟机         return;     }     onVmCreated(env);//表示虚拟创建完成,但是里面是空实现     /*      * Register android functions.      */     if (startReg(env) options[i]; options.push_back(std::make_pair(std::string(option->optionString), option- >extraInfo)); } bool ignore_unrecognized = args->ignoreUnrecognized; //创建Runtime对象 if (!Runtime::Create(options, ignore_unrecognized)) { return JNI_ERR; } .... Runtime* runtime = Runtime::Current(); bool started = runtime->Start(); //Runtime启动 if (!started) { //如果启动失败,则释放当前的JniEnv & JavaVM 对象; delete Thread::Current()->GetJniEnv(); delete runtime->GetJavaVM(); LOG(WARNING) GetJniEnv(); *p_vm = runtime->GetJavaVM(); } 1.2.2 Runtime::Create

组成 Android 虚拟机的核心自系统包括但不限于 Runtime、ClassLoader System、Execution、Engine System、Heap Manager 和 GC 系统、JIT、JNI 环境等;

调用了 Runtime::Init 方法,用于初始化虚拟机,包括:创建 Java 虚拟机、创建 Heap 堆管理对象、加载主线程等

art/runtime/runtime.cc //两个参数,内部主要是解析虚拟机的参数 bool Runtime::Create(const RuntimeOptions& raw_options, bool ignore_unrecognized) { RuntimeArgumentMap runtime_options; return ParseOptions(raw_options, ignore_unrecognized, &runtime_options) && Create(std::move(runtime_options)); //调用下面的一个参数的Create函数 } bool Runtime::Create(RuntimeArgumentMap&& runtime_options) { //一个进程只有一个Runtime实列,定义在头文件中 static Runtime* instance_; //static 保证全局唯一 if (Runtime::instance_ != nullptr) { return false; } instance_ = new Runtime; //C++ 创建一个Runtime对象 if (!instance_->Init(std::move(runtime_options))) {//调用Runtime的Init方法 // TODO: Currently deleting the instance will abort the runtime on destruction. Now This will // leak memory, instead. Fix the destructor. b/19100793. // delete instance_; instance_ = nullptr; return false; } return true; }

Runtime::Create 成功启动了一个虚拟机后,接下去会通过 Init 函数来初始化;

1.2.3 Runtime::Init bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { ... heap_ = new gc::Heap(...); // 创建堆管理对象 ... BlockSignals(); //信号相关,后面信号专题再继续展开分析 InitPlatformSignalHandlers(); java_vm_ = JavaVMExt::Create(this, runtime_options, &error_msg); // 创建 Java 虚拟机对象 Thread::Startup(); Thread* self = Thread::Attach("main", false, nullptr, false); // 主线程 attach if (UNLIKELY(IsAotCompiler())) { class_linker_ = new AotClassLinker(intern_table_); } else { class_linker_ = new ClassLinker(intern_table_); //创建ClassLinker实例负责管理java class。 } if (GetHeap()->HasBootImageSpace()) { // 当前 Heap 是否包含 Boot Image(比如 boot.art) bool result = class_linker_->InitFromBootImage(&error_msg); ... } else { if (runtime_options.Exists(Opt::BootClassPathDexList)) { boot_class_path.swap(*runtime_options.GetOrDefault(Opt::BootClassPathDexList)); } else { OpenDexFiles(dex_filenames, dex_locations, runtime_options.GetOrDefault(Opt::Image), &boot_class_path); } instruction_set_ = runtime_options.GetOrDefault(Opt::ImageInstructionSet); if (!class_linker_->InitWithoutImage(std::move(boot_class_path), &error_msg)) { LOG(ERROR) GetException()); self->ClearException(); // Pre-allocate a NoClassDefFoundError for the common case of failing to find a system class // ahead of checking the application's class loader. self->ThrowNewException("Ljava/lang/NoClassDefFoundError;", "Class not found using the boot class loader; no stack trace available"); pre_allocated_NoClassDefFoundError_ = GcRoot(self->GetException()); self->ClearException(); return true; } 1.2.4 JavaVMExt::Create //创建C++ JavaVMExt对象 //内部持有当前进程全局唯一的Runtime对象; std::unique_ptr JavaVMExt::Create(Runtime* runtime, const RuntimeArgumentMap& runtime_options, std::string* error_msg) NO_THREAD_SAFETY_ANALYSIS { std::unique_ptr java_vm(new JavaVMExt(runtime, runtime_options, error_msg)); //构造函数 if (java_vm && java_vm->globals_.IsValid() && java_vm->weak_globals_.IsValid()) { return java_vm; } return nullptr; } 1.2.4 Thread::Startup

主要是创建

art/runtime/Thread.cc void Thread::Startup() { CHECK(!is_started_); is_started_ = true; ...... // Allocate a TLS slot. CHECK_PTHREAD_CALL(pthread_key_create, (&Thread::pthread_key_self_, Thread::ThreadExitCallback),"self key"); // Double-check the TLS slot allocation. if (pthread_getspecific(pthread_key_self_) != nullptr) { LOG(FATAL) ClearException(); } return false; } } else {//因为第四个参数是false, 所以走这个分支; // These aren't necessary, but they improve diagnostics for unit tests & command-line tools. if (thread_name != nullptr) { self->tlsPtr_.name->assign(thread_name); ::art::SetThreadName(thread_name); //设置线程名称 } else if (self->GetJniEnv()->check_jni) { LOG(WARNING) GetThreadList(), runtime->GetJavaVM()); //调用Thread.Init函数 Runtime::Current()->EndThreadBirth(); if (!init_success) { delete self; return nullptr; } } } self->InitStringEntryPoints(); CHECK_NE(self->GetState(), kRunnable); self->SetState(kNative); // Run the action that is acting on the peer. if (!peer_action(self)) { //函数指针处理,具体实现是上面的实现在create_peer_action runtime->GetThreadList()->Unregister(self); // Unregister deletes self, no need to do this here. return nullptr; } { ScopedObjectAccess soa(self); runtime->GetRuntimeCallbacks()->ThreadStart(self); } return self; } 1.2.6 Thread::Init bool Thread::Init(ThreadList* thread_list, JavaVMExt* java_vm, JNIEnvExt* jni_env_ext) { ..... SetUpAlternateSignalStack(); if (!InitStackHwm()) { return false; } InitCpu(); InitTlsEntryPoints(); RemoveSuspendTrigger(); InitCardTable(); InitTid(); interpreter::InitInterpreterTls(this); .... if (jni_env_ext != nullptr) { DCHECK_EQ(jni_env_ext->vm, java_vm); DCHECK_EQ(jni_env_ext->self, this); tlsPtr_.jni_env = jni_env_ext; } else { std::string error_msg; tlsPtr_.jni_env = JNIEnvExt::Create(this, java_vm, &error_msg); //创建当前线程的JNIEnvExt对象 if (tlsPtr_.jni_env == nullptr) { LOG(ERROR) GetClassLinker()->RunRootClinits(); // The thread counts as started from now on. We need to add it to the ThreadGroup. For regular // threads, this is done in Thread.start() on the Java side. { // This is only ever done once. There's no benefit in caching the method. jmethodID thread_group_add = soa.Env()->GetMethodID(WellKnownClasses::java_lang_ThreadGroup, "add", "(Ljava/lang/Thread;)V"); CHECK(thread_group_add != nullptr); ScopedLocalRef thread_jobject( soa.Env(), soa.Env()->AddLocalReference(Thread::Current()->GetPeer())); soa.Env()->CallNonvirtualVoidMethod(runtime->GetMainThreadGroup(), WellKnownClasses::java_lang_ThreadGroup, thread_group_add, thread_jobject.get()); Thread::Current()->AssertNoPendingException(); } } 1.2.11 Thread::CreatePeer void Thread::CreatePeer(const char* name, bool as_daemon, jobject thread_group) { Runtime* runtime = Runtime::Current(); JNIEnv* env = tlsPtr_.jni_env; if (thread_group == nullptr) { thread_group = runtime->GetMainThreadGroup(); } jint thread_priority = GetNativePriority(); jboolean thread_is_daemon = as_daemon; ScopedLocalRef peer(env, env->AllocObject(WellKnownClasses::java_lang_Thread)); { ScopedObjectAccess soa(this); tlsPtr_.opeer = soa.Decode(peer.get()).Ptr(); } //C 调用Java,并且java中的线程名获取也是main env->CallNonvirtualVoidMethod(peer.get(), WellKnownClasses::java_lang_Thread, WellKnownClasses::java_lang_Thread_init, thread_group, thread_name.get(), thread_priority, thread_is_daemon); //Java中的nativePeer指向C++ 中的Thread地址 env->SetLongField(peer.get(), WellKnownClasses::java_lang_Thread_nativePeer, reinterpret_cast(self)); }

到这里 AndroidRuntime::startVm函数终于结束,并且返回true,继续往下执行;

二、小结

第一阶段主要工作是从libart.so提取出JNI初始函数JNI_CreateJavaVM等,然后读取一些系统属性作为参数调用JNI_CreateJavaVM创建虚拟机,包括C++ 中的Runtime, Thread对象, 返回了两个JNI 非常重要的结构 C++ JavaVMExt对象(进程唯一)  & JNIEnvExt对象(线程唯一)

JNI 注册下一篇文章再继续分析;



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3