美文网首页
Dalvik虚拟机启动过程

Dalvik虚拟机启动过程

作者: DroidMind | 来源:发表于2017-09-14 18:44 被阅读0次

    涉及源码(Android 4.4.2):
    frameworks/base/cmds/app_process/app_main.cpp
    /frameworks/base/core/jni/AndroidRuntime.cpp
    /libnativehelper/JniInvocation.cpp
    /dalvik/vm/Jni.cpp
    /dalvik/vm/JniInternal.h
    /libnativehelper/include/nativehelper/jni.h

    首先来看看app_main.cpp的main方法,它是启动虚拟机的入口方法。

    frameworks/base/cmds/app_process/app_main.cpp

    int main(int argc, char* const argv[])
    {
       // zygote进程是由init进程通过fork而来
        AppRuntime runtime;
      
        if (zygote) {
            runtime.start("com.android.internal.os.ZygoteInit",
                    startSystemServer ? "start-system-server" : "");
        }
    }
    

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

    void AndroidRuntime::start(const char* className, const char* options)
    {
    
        /* start the virtual machine */
        JniInvocation jni_invocation;
        // 1、初始化JNI相关的函数
        jni_invocation.Init(NULL);
        JNIEnv* env;
        // 2、启动虚拟机
        if (startVm(&mJavaVM, &env) != 0) {
            return;
        }
        onVmCreated(env);
    
        // 3、注册JNI函数
        if (startReg(env) < 0) {
            ALOGE("Unable to register all android natives\n");
            return;
        }
    }
    

    一、初始化JNI相关的函数

    /libnativehelper/JniInvocation.cpp

    bool JniInvocation::Init(const char* library) {
    #ifdef HAVE_ANDROID_OS
      char default_library[PROPERTY_VALUE_MAX];
      property_get(kLibrarySystemProperty, default_library, kLibraryFallback);
    #else
      const char* default_library = kLibraryFallback;
    #endif
      if (library == NULL) {
        library = default_library;
      }
      // 通过dlopen加载libdvm.so,libdvm.so是dalvik vm的核心库
      handle_ = dlopen(library, RTLD_NOW);
      //从libdvm.so中找到JNI_GetDefaultJavaVMInitArgs、NI_CreateJavaVM和JNI_GetCreateJavaVMs这三个函数指针。
      if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
                      "JNI_GetDefaultJavaVMInitArgs")) {
        return false;
      }
      if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
                      "JNI_CreateJavaVM")) {
        return false;
      }
      if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
                      "JNI_GetCreatedJavaVMs")) {
        return false;
      }
      return true;
    }
    
    

    二、启动虚拟机

    int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
    {
     // 前面是初始化操作,重点是整个方法
     if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
            ALOGE("JNI_CreateJavaVM failed\n");
            goto bail;
        }
    }
    

    JNI_CreateJavaVM方法就是前面libdvm.so中的方法,它就是创建虚拟机的方法。

    下面来看看这个JNI_CreateJavaVM方法

    /dalvik/vm/Jni.cpp

    jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
        const JavaVMInitArgs* args = (JavaVMInitArgs*) vm_args;
        
        //1、gDvm是一个静态的数据结构,数据类型为结构体DvmGlobals
        // 虚拟机的大部分数据都是有它来存放
        memset(&gDvm, 0, sizeof(gDvm));
    
        //2、创建JavaVMExt对象,其实也是JavaVM对象
        JavaVMExt* pVM = (JavaVMExt*) calloc(1, sizeof(JavaVMExt));
        pVM->funcTable = &gInvokeInterface;
        pVM->envList = NULL;
        dvmInitMutex(&pVM->envListLock);
    
       
        gDvmJni.jniVm = (JavaVM*) pVM;
    
       // 3、创建JNIEnvExt对象,其实对应的也是JNIEnv对象
        JNIEnvExt* pEnv = (JNIEnvExt*) dvmCreateJNIEnv(NULL);
    
        //4、启动虚拟机
        gDvm.initializing = true;
        std::string status =
                dvmStartup(argc, argv.get(), args->ignoreUnrecognized, (JNIEnv*)pEnv);
        gDvm.initializing = false;
        
        *p_env = (JNIEnv*) pEnv;
        *p_vm = (JavaVM*) pVM;
       
    }
    
    1、重置gDvm结构

    DvmGlobals,该结构体是Dalvik的核心数据结构,几乎所有的重要成员等都通过gDvm来管理。

    2、创建JavaVMExt对象

    JavaVMExt对象的funcTable成员用来保存Dalvik虚拟机实例函数表,从代码可以看到,这个函数表为gInvokeInterface,gInvokeInterface是一个类型为JNIInvokeInterface的结构体。

    /dalvik/vm/jni.cpp

    static const struct JNIInvokeInterface gInvokeInterface = {  
        NULL,  
        NULL,  
        NULL,  
    
        DestroyJavaVM,  
        AttachCurrentThread,  
        DetachCurrentThread,  
    
        GetEnv,  
    
        AttachCurrentThreadAsDaemon,  
    };  
    
    3、创建JNIEnvExt对象

    下面来看看dvmCreateJNIEnv函数

    JNIEnv* dvmCreateJNIEnv(Thread* self) {
        JavaVMExt* vm = (JavaVMExt*) gDvmJni.jniVm;
        
        // 1、创建JNIEnvExt对象
        // Dalvik虚拟机里JNI的所有函数都封装在gNativeInterface中
        JNIEnvExt* newEnv = (JNIEnvExt*) calloc(1, sizeof(JNIEnvExt));
        newEnv->funcTable = &gNativeInterface;
        if (self != NULL) {
            dvmSetJniEnvThreadId((JNIEnv*) newEnv, self);
            assert(newEnv->envThreadId != 0);
        } else {
            newEnv->envThreadId = 0x77777775;
            newEnv->self = (Thread*) 0x77777779;
        }
        if (gDvmJni.useCheckJni) {
            dvmUseCheckedJniEnv(newEnv);
        }
    
        ScopedPthreadMutexLock lock(&vm->envListLock);
    
        // 2、将JNIEnvExt插入到JavaVMExt对象的成员变量envList列表的头部
        newEnv->next = vm->envList;
        assert(newEnv->prev == NULL);
        if (vm->envList == NULL) {
            // rare, but possible
            vm->envList = newEnv;
        } else {
            vm->envList->prev = newEnv;
        }
        vm->envList = newEnv;
        
        return (JNIEnv*) newEnv;
    }
    

    (1)结构体JNINativeInterface用来描述一个本地接口表。当我们需要在C/C++代码在中调用Java函数,就要用到这个本地接口表

    static const struct JNINativeInterface gNativeInterface = {  
        ......  
          
        FindClass,  
      
        ......  
      
        GetMethodID,  
          
        ......  
      
        CallObjectMethod,  
          
        ......  
      
        GetFieldID,  
      
        ......  
          
        SetIntField,  
          
        ......  
      
        RegisterNatives,  
        UnregisterNatives,  
      
        ......  
      
        GetJavaVM,  
      
        ......  
    };
    

    (2)每一个Dalvik虚拟机实例还有一个JNI环境列表,这个列表保存JavaVMExt对象的成员变量envList中。JavaVMExt的JNI环境列表就是JNIEnvExt列表。每一个Attach到Dalvik虚拟机中去的线程都有一个对应的JNIEnvExt,用来描述它的JNI环境。

    他们之间的关系图如下图所示:

    /dalvik/vm/JniInternal.h
    /libnativehelper/include/nativehelper/jni.h

    vmstart.png
    4、初始化并启动虚拟机

    dalvik/vm/init.cpp

    std::string dvmStartup(int argc, const char* const argv[],
            bool ignoreUnrecognized, JNIEnv* pEnv)
    {
         /*
         * Initialize components.
         */
        dvmQuasiAtomicsStartup();
        if (!dvmAllocTrackerStartup()) {
            return "dvmAllocTrackerStartup failed";
        }
        if (!dvmGcStartup()) {
            return "dvmGcStartup failed";
        }
        if (!dvmThreadStartup()) {
            return "dvmThreadStartup failed";
        }
        if (!dvmInlineNativeStartup()) {
            return "dvmInlineNativeStartup";
        }
        if (!dvmRegisterMapStartup()) {
            return "dvmRegisterMapStartup failed";
        }
        if (!dvmInstanceofStartup()) {
            return "dvmInstanceofStartup failed";
        }
        if (!dvmClassStartup()) {
            return "dvmClassStartup failed";
        }
    
        if (!dvmFindRequiredClassesAndMembers()) {
            return "dvmFindRequiredClassesAndMembers failed";
        }
    
        if (!dvmStringInternStartup()) {
            return "dvmStringInternStartup failed";
        }
        if (!dvmNativeStartup()) {
            return "dvmNativeStartup failed";
        }
        if (!dvmInternalNativeStartup()) {
            return "dvmInternalNativeStartup failed";
        }
        if (!dvmJniStartup()) {
            return "dvmJniStartup failed";
        }
        if (!dvmProfilingStartup()) {
            return "dvmProfilingStartup failed";
        }
    
        if (!dvmCreateInlineSubsTable()) {
            return "dvmCreateInlineSubsTable failed";
        }
    
        if (!dvmValidateBoxClasses()) {
            return "dvmValidateBoxClasses failed";
        }
    
        if (!dvmPrepMainForJni(pEnv)) {
            return "dvmPrepMainForJni failed";
        }
    
        if (!dvmInitClass(gDvm.classJavaLangClass)) {
            return "couldn't initialized java.lang.Class";
        }
    
        if (!registerSystemNatives(pEnv)) {
            return "couldn't register system natives";
        }
    
        if (!dvmCreateStockExceptions()) {
            return "dvmCreateStockExceptions failed";
        }
    
        if (!dvmPrepMainThread()) {
            return "dvmPrepMainThread failed";
        }
    
        if (dvmReferenceTableEntries(&dvmThreadSelf()->internalLocalRefTable) != 0)
        {
            ALOGW("Warning: tracked references remain post-initialization");
            dvmDumpReferenceTable(&dvmThreadSelf()->internalLocalRefTable, "MAIN");
        }
    
        if (!dvmDebuggerStartup()) {
            return "dvmDebuggerStartup failed";
        }
    
        if (!dvmGcStartupClasses()) {
            return "dvmGcStartupClasses failed";
        }
    
        /*
         * Init for either zygote mode or non-zygote mode.  The key difference
         * is that we don't start any additional threads in Zygote mode.
         */
        if (gDvm.zygote) {
            if (!initZygote()) {
                return "initZygote failed";
            }
        } else {
            if (!dvmInitAfterZygote()) {
                return "dvmInitAfterZygote failed";
            }
        }
    
    }
    
    

    主要用来初始化Dalvik虚拟机

    三、注册JNI函数

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

    /*static*/ int AndroidRuntime::startReg(JNIEnv* env)
    {
        // 注册JNI函数,gRegJNI是一个全局数组
        if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
            env->PopLocalFrame(NULL);
            return -1;
        }
        env->PopLocalFrame(NULL);
    
        return 0;
    }
    
    static const RegJNIRec gRegJNI[] = {
        REG_JNI(register_android_debug_JNITest),
        REG_JNI(register_com_android_internal_os_RuntimeInit),
        REG_JNI(register_android_os_SystemClock),
        REG_JNI(register_android_util_EventLog),
        REG_JNI(register_android_util_Log),
        REG_JNI(register_android_util_FloatMath),
        REG_JNI(register_android_text_format_Time),
        REG_JNI(register_android_content_AssetManager),
        REG_JNI(register_android_content_StringBlock),
        REG_JNI(register_android_content_XmlBlock),
        REG_JNI(register_android_emoji_EmojiFactory),
        REG_JNI(register_android_text_AndroidCharacter),
        REG_JNI(register_android_text_AndroidBidi),
        REG_JNI(register_android_view_InputDevice),
        REG_JNI(register_android_view_KeyCharacterMap),
        REG_JNI(register_android_os_Process),
        REG_JNI(register_android_os_SystemProperties),
        REG_JNI(register_android_os_Binder),
        // ...还是很多
        }
    

    参考文章:
    http://www.infoq.com/cn/articles/android-in-depth-dalvik
    http://blog.csdn.net/luoshengyang/article/details/8885792

    相关文章

      网友评论

          本文标题:Dalvik虚拟机启动过程

          本文链接:https://www.haomeiwen.com/subject/pwadsxtx.html