Android5.1.1源码 - 虚拟机的建立

Android5.1.1源码 - 虚拟机的建立

@(Android研究)[Android|源码|虚拟机]java


[TOC]android


虚拟机启动时的函数调用路径:数组

app_main.cc - main
  |-- AndroidRuntime::start
      |-- AndroidRuntime::startVm
          |-- JNI_CreateJavaVM

当init进程启动zygote进程时会建立虚拟机,下是zygote代码的main函数,本文从这里开始分析虚拟机如何建立,这个函数在文件"frameworks/base/cmds/app_process/app_main.cpp"中,下面是它的源码:app

int main(int argc, char* const argv[])
{
    ......

    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // 处理命令行参数
    // 忽略 argv[0]
    argc--;
    argv++;

    // Everything up to '--' or first non '-' arg goes to the vm.
    //
    // The first argument after the VM args is the "parent dir", which
    // is currently unused.
    //
    // After the parent dir, we expect one or more the following internal
    // arguments :
    //
    // --zygote : Start in zygote mode
    // --start-system-server : 启动系统服务
    // --application : Start in application (stand alone, non zygote) mode.
    // --nice-name : The nice name for this process.
    //
    // For non zygote starts, these arguments will be followed by
    // the main class name. All remaining arguments are passed to
    // the main method of this class.
    //
    // For zygote starts, all remaining arguments are passed to the zygote.
    // main function.
    //
    // Note that we must copy argument string values since we will rewrite the
    // entire argument block when we apply the nice name to argv0.

    int i;
    for (i = 0; i < argc; i++) {
        if (argv[i][0] != '-') {
            break;
        }
        if (argv[i][1] == '-' && argv[i][2] == 0) {
            ++i; // Skip --.
            break;
        }
        runtime.addOption(strdup(argv[i]));
    }

    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    Vector<String8> args;
    if (!className.isEmpty()) {
        // We're not in zygote mode, the only argument we need to pass
        // to RuntimeInit is the application argument.
        //
        // The Remainder of args get passed to startup class main(). Make
        // copies of them before we overwrite them with the process name.
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);
    } else {
        // We're in zygote mode.
        maybeCreateDalvikCache();

        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }

        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                ABI_LIST_PROPERTY);
            return 11;
        }

        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);

        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }

    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string());
    }

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }
}

**runtime.start(...)**语句启动了Android运行时,在启动Android运行时的同时会启动虚拟机。main函数中的局部变量runtime是AppRuntime类的对象,这个类的代码定义在文件"frameworks/base/cmds/app_process/app_main.cpp"中,AppRuntime类继承了AndroidRuntime类,而start函数就是AndroidRuntime类的成员函数。ide

AndroidRuntime类定义在文件"frameworks/base/core/jni/AndroidRuntime.cpp"中,下面是AndroidRuntime::start函数的代码:函数

/*
 * 启动Android运行时。它启动虚拟机并调用经过"className"参数所指定的类名中
 * 的"static void main(String[] args)"方法。
 *
 * 向main函数传入两个参数:类名和被指定的选项字符串。
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());

    ......

    /* 启动虚拟机。 */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);  // 初始化JNI API接口
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);  // 在zygote中这个函数什么都不作。

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    /*
     * 咱们要调用main(),将一个字符串数组当作参数传入。
     * 目前,咱们有两个参数,类名和一个选项字符串。
     * 建立一个数组来保存它们。
     */
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;

    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);

    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }

    /*
     * 启动Start VM。这个线程成为VM的主线程,直到VM结束前不会返回。
     * 
     * 对于zygote而言除非设备关机不然这个线程是不会退出的,将zygote
     * 比做服务端,这个服务端会一直等待并处理各类客户端的请求。
     */
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            // 调用Java方法。
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    free(slashClassName);

    ALOGD("Shutting down VM\n");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main thread\n");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanly\n");
}

这个函数主要作了下面三件事情:ui

  1. 调用**jni_invocation.Init(NULL);**语句初始化JNI API。
  2. 调用startVm函数建立了虚拟机。
  3. env->CallStaticVoidMethod语句调用类的main方法。

这个函数中调用了**onVmCreated(env);**语句,对于zygote来讲,这个函数不作任何事情。this

jni_invocation虽然是AndroidRuntime::start函数的局部变量,可是对于zygote而言除非设备关机不然是不会退出AndroidRuntime::start函数的。对于普通APP,除非APP结束不然也不会退出AndroidRuntime::start函数。在另外一篇分析zygote启动过程的文章中会说明缘由。命令行

JniInvocation::Init这个函数用于初始化JNI调用,这个函数在文件libnativehelper/JniInvocation.cpp中,下面是这个函数的代码:线程

/**
 * 初始化JNI调用API。参数library应当传入可供dlopen打开的有效的共享库,
 * 这个共享库提供一个JNI调用实现,或者参数library被传入null则将经过
 * persist.sys.dalvik.vm.lib使用默认值。
 */
bool JniInvocation::Init(const char* library) {
#ifdef HAVE_ANDROID_OS
  char buffer[PROPERTY_VALUE_MAX];
#else
  char* buffer = NULL;
#endif
  // 得到共享库名。
  library = GetLibrary(library, buffer);

  // 加载这个共享库。
  handle_ = dlopen(library, RTLD_NOW);
  if (handle_ == NULL) {
    if (strcmp(library, kLibraryFallback) == 0) {
      // Nothing else to try.
      ALOGE("Failed to dlopen %s: %s", library, dlerror());
      return false;
    }
    // Note that this is enough to get something like the zygote
    // running, we can't property_set here to fix this for the future
    // because we are root and not the system user. See
    // RuntimeInit.commonInit for where we fix up the property to
    // avoid future fallbacks. http://b/11463182
    ALOGW("Falling back from %s to %s after dlopen error: %s",
          library, kLibraryFallback, dlerror());
    library = kLibraryFallback;
    handle_ = dlopen(library, RTLD_NOW);
    if (handle_ == NULL) {
      ALOGE("Failed to dlopen %s: %s", library, dlerror());
      return false;
    }
  }

  // 找到符号JNI_GetDefaultJavaVMInitArgs。
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
                  "JNI_GetDefaultJavaVMInitArgs")) {
    return false;
  }

  // 找到符号JNI_CreateJavaVM。
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
                  "JNI_CreateJavaVM")) {
    return false;
  }

  // 找到符号JNI_GetCreatedJavaVMs。
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
                  "JNI_GetCreatedJavaVMs")) {
    return false;
  }
  return true;
}

这个函数作了下面两件事情:

  1. 得到包含JNI接口的共享库名。
  2. 加载这个共享库。
  3. 从这个共享库中得到了三个符号的地址:JNI_GetDefaultJavaVMInitArgs、JNI_CreateJavaVM和JNI_GetCreatedJavaVMs。

JniInvocation类中的成员变量handle_保存了共享库的句柄,成员函数JNI_GetDefaultJavaVMInitArgs_、*JNI_CreateJavaVM_JNI_GetCreatedJavaVMs_*均保存了从共享库中得到的函数地址。

JniInvocation::Init调用了JniInvocation::GetLibrary函数得到了共享库名,这个共享库中有JNI函数的实现,这个函数在文件libnativehelper/JniInvocation.cpp中,下面是它的代码:

#ifdef HAVE_ANDROID_OS
static const char* kLibrarySystemProperty = "persist.sys.dalvik.vm.lib.2";
static const char* kDebuggableSystemProperty = "ro.debuggable";
static const char* kDebuggableFallback = "0";  // Not debuggable.
#endif
static const char* kLibraryFallback = "libart.so";

const char* JniInvocation::GetLibrary(const char* library, char* buffer) {
#ifdef HAVE_ANDROID_OS
  const char* default_library;

  char debuggable[PROPERTY_VALUE_MAX];
  property_get(kDebuggableSystemProperty, debuggable, kDebuggableFallback);

  if (strcmp(debuggable, "1") != 0) {
    // Not a debuggable build.
    // Do not allow arbitrary library.  This
    // will also ignore the default library, but initialize to fallback
    // for cleanliness.
    library = kLibraryFallback;
    default_library = kLibraryFallback;
  } else {
    // Debuggable build.
    // Accept the library parameter. For the case it is NULL, load the default
    // library from the system property.
    if (buffer != NULL) {
      property_get(kLibrarySystemProperty, buffer, kLibraryFallback);
      default_library = buffer;
    } else {
      // 若是没有指定缓冲区,使用备用的默认值。
      default_library = kLibraryFallback;
    }
  }
#else
  UNUSED(buffer);
  const char* default_library = kLibraryFallback;
#endif
  if (library == NULL) {
    library = default_library;
  }

  return library;
}

能够发现JniInvocation::GetLibrary函数中默认的库是kLibraryFallback,而这个变量的值为libart.so,这个函数的返回值与kLibrarySystemProperty变量也有关系,而这个变量中保存的属性对应的值一般为libart.so。因此在这里我武断的认定这个函数的返回值总为libart.so以便后面分析。

对AndroidRuntime::start函数中所执行**jni_invocation.Init(NULL);**语句作一个总结

  1. 它加载了libart.so。
  2. jni_invocation对象中保存了libart.so的句柄。
  3. jni_invocation对象中保存了JNI_GetDefaultJavaVMInitArgs、JNI_CreateJavaVM和JNI_GetCreatedJavaVMs这三个函数的地址。

继续对AndroidRuntime::start函数进行分析,在执行完**jni_invocation.Init(NULL);**语句后紧接着调用了startVm函数,这个函数启动了虚拟机。这个函数在文件frameworks/base/core/jni/AndroidRuntime.cpp中,下面是它的源码:

/*
 * Start the Dalvik Virtual Machine.
 * (PS:这里翻译过来是:启动Dalvik虚拟机,我认为是这只不过是注释内容还未被修改,而实际上启动的已经不是dalvik虚拟机了)
 *
 * Various arguments, most determined by system properties, are passed in.
 * The "mOptions" vector is updated.
 *
 * CAUTION: when adding options in here, be careful not to put the
 * char buffer inside a nested scope.  Adding the buffer to the
 * options using mOptions.add() does not copy the buffer, so if the
 * buffer goes out of scope the option may be overwritten.  It's best
 * to put the buffer at the top of the function so that it is more
 * unlikely that someone will surround it in a scope at a later time
 * and thus introduce a bug.
 *
 * Returns 0 on success.
 */
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
    int result = -1;
    JavaVMInitArgs initArgs;

    ......

    // checkjni属性。
    bool checkJni = false;
    property_get("dalvik.vm.checkjni", propBuf, "");
    if (strcmp(propBuf, "true") == 0) {
        checkJni = true;
    } else if (strcmp(propBuf, "false") != 0) {
        /* 属性即不为真也不为假;转到内核参数。 */
        property_get("ro.kernel.android.checkjni", propBuf, "");
        if (propBuf[0] == '1') {
            checkJni = true;
        }
    }
    ALOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
    if (checkJni) {
        /* extended JNI checking */
        addOption("-Xcheck:jni");

        /* 设置JNI全局引用上限 */
        addOption("-Xjnigreflimit:2000");

        /* with -Xcheck:jni, 这提供JNI函数调用跟踪 */
        //addOption("-verbose:jni");
    }

    // 根据属性得到虚拟机的执行模式。
    property_get("dalvik.vm.execution-mode", propBuf, "");
    if (strcmp(propBuf, "int:portable") == 0) {
        executionMode = kEMIntPortable;
    } else if (strcmp(propBuf, "int:fast") == 0) {
        executionMode = kEMIntFast;
    } else if (strcmp(propBuf, "int:jit") == 0) {
        executionMode = kEMJitCompiler;
    }

    ......
    
    /* Force interpreter-only mode for selected opcodes. Eg "1-0a,3c,f1-ff" */
    parseRuntimeOption("dalvik.vm.jit.op", jitOpBuf, "-Xjitop:");

    /* Force interpreter-only mode for selected methods */
    parseRuntimeOption("dalvik.vm.jit.method", jitMethodBuf, "-Xjitmethod:");

    // 向mOptions中添加执行模式。
    if (executionMode == kEMIntPortable) {
        addOption("-Xint:portable");
    } else if (executionMode == kEMIntFast) {
        addOption("-Xint:fast");
    } else if (executionMode == kEMJitCompiler) {
        addOption("-Xint:jit");
    }

    // libart允许libdvm flags,但反过来不行,因此仅libart的状况下才传入一些选项。
    property_get("persist.sys.dalvik.vm.lib.2", dalvikVmLibBuf, "libart.so");
    bool libart = (strncmp(dalvikVmLibBuf, "libart", 6) == 0);

    if (libart) {
        ......
    }

    ......

    initArgs.version = JNI_VERSION_1_4;
    initArgs.options = mOptions.editArray();
    initArgs.nOptions = mOptions.size();
    initArgs.ignoreUnrecognized = JNI_FALSE;

    /*
     * 初始化VM。
     *
     * JavaVM*做用于每一个进程,JNIEnv*做用于每一个线程(The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.)。
     * 
     * 若是这个调用成功,则VM就绪,and we can start issuing
     * JNI calls.
     */
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        ALOGE("JNI_CreateJavaVM failed\n");
        goto bail;
    }

    result = 0;

bail:
    return result;
}

AndroidRuntime::startVm函数主要作了两件事情:

  1. 解析系统属性,并将系统属性添加到mOptions中,而后将mOptions封装到initArgs中。
  2. 调用JNI_CreateJavaVM函数建立一个Java虚拟机。

系统属性主要经过property_get函数得到,这个函数会去系统属性文件中读取属性。

当要添加一个新的选项时会调用AndroidRuntime::addOption函数,它向mOptions中添加一个JavaVMOption对象,这个函数在frameworks/base/core/jni/AndroidRuntime.cpp文件中,下面是它的源码:

void addOption(const char* optionString, void* extra_info = NULL);

void AndroidRuntime::addOption(const char* optionString, void* extraInfo)
{
    JavaVMOption opt;
    opt.optionString = optionString;
    opt.extraInfo = extraInfo;
    mOptions.add(opt);
}

下面开始分析JNI_CreateJavaVM函数,这个定义在libnativehelper/JniInvocation.cpp文件中,下面是它的源码:

extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
  return JniInvocation::GetJniInvocation().JNI_CreateJavaVM(p_vm, p_env, vm_args);
}

JniInvocation::GetJniInvocation()函数得到的是JniInvocation类的实例,JniInvocation::GetJniInvocation().JNI_CreateJavaVM调用的是JniInvocation类中非静态成员函数JNI_CreateJavaVM,下面是这个成员函数的源码:

jint JniInvocation::JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
  return JNI_CreateJavaVM_(p_vm, p_env, vm_args);
}

JNI_CreateJavaVM_是JniInvocation类中的非静态成员变量,它指向的是前面所加载的libart.so中的JNI_CreateJavaVM函数,这个成员变量在JniInvocation::Init函数中被赋值。

libart.so中的JNI_CreateJavaVM函数建立了虚拟机,它的源码art/runtime/jni_internal.cc文件中,下面是这个函数的源码:

/**
 * 建立虚拟机。
 * 参数p_vm和p_env是输出参数。
 * 参数vm_args是输入参数,这个参数保存的是虚拟机建立过程当中须要用到的选项。
 */
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
  const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);

  // 检查Jni版本。
  if (IsBadJniVersion(args->version)) {
    LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version;
    return JNI_EVERSION;
  }

  // 将全部的虚拟机选项均保存到options中。
  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;
  }

  // 启动运行时环境。
  Runtime* runtime = Runtime::Current();
  bool started = runtime->Start();
  if (!started) {
    delete Thread::Current()->GetJniEnv();
    delete runtime->GetJavaVM();
    LOG(WARNING) << "CreateJavaVM failed";
    return JNI_ERR;
  }

  // 输出参数。
  *p_env = Thread::Current()->GetJniEnv();
  *p_vm = runtime->GetJavaVM();
  return JNI_OK;
}

JNI_CreateJavaVM函数主要作了两件事情:

  1. Runtime::Create语句建立运行时环境。
  2. **runtime->Start();**语句启动运行时环境。

RuntimeOptions类型的定义在文件art/runtime/runtime.h中:

typedef std::vector<std::pair<std::string, const void*>> RuntimeOptions;

Runtime::Create函数是一个静态函数在文件art/runtime/runtime.cc中,下面是它的源码:

bool Runtime::Create(const RuntimeOptions& options, bool ignore_unrecognized) {
  // TODO: acquire a static mutex on Runtime to avoid racing.
  if (Runtime::instance_ != NULL) {
    return false;
  }
  InitLogging(NULL);  // Calls Locks::Init() as a side effect.
  instance_ = new Runtime;
  if (!instance_->Init(options, ignore_unrecognized)) {
    delete instance_;
    instance_ = NULL;
    return false;
  }
  return true;
}

经过分析上面的代码能够发现Runtime类被设计为单例模式,单例对象保存在instance_中,而后又调用了Init函数。

Runtime::Init函数在文件art/runtime/runtime.cc中,下面是它的源码:

bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) {
  CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);

  MemMap::Init();

  std::unique_ptr<ParsedOptions> options(ParsedOptions::Create(raw_options, ignore_unrecognized));

  ......

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

  Thread::Startup();

  // ClassLinker needs an attached thread, but we can't fully attach a thread without creating
  // objects. We can't supply a thread group yet; it will be fixed later. Since we are the main
  // thread, we do not get a java peer.
  Thread* self = Thread::Attach("main", false, nullptr, false);

  ......

  VLOG(startup) << "Runtime::Init exiting";
  return true;
}

这个函数中的new JavaVMExt语句建立了JavaVMExt对象,一个虚拟机有且仅有一个JavaVMExt对象,JavaVMExt类型继承了JavaVM类型,能够去查看"art/runtime/jni_internal.h"文件。Thread::Attach函数将虚拟机附加到主线程上。

Thread::Attach函数的源码在文件"art/runtime/thread.cc"文件中,下面是它的源码:

Thread* Thread::Attach(const char* thread_name, bool as_daemon, jobject thread_group,
                       bool create_peer) {
  Thread* self;
  Runtime* runtime = Runtime::Current();
  if (runtime == nullptr) {
    LOG(ERROR) << "Thread attaching to non-existent runtime: " << thread_name;
    return nullptr;
  }
  {
    MutexLock mu(nullptr, *Locks::runtime_shutdown_lock_);
    if (runtime->IsShuttingDownLocked()) {
      ......
    } else {
      Runtime::Current()->StartThreadBirth();
      self = new Thread(as_daemon);
      self->Init(runtime->GetThreadList(), runtime->GetJavaVM());
      Runtime::Current()->EndThreadBirth();
    }
  }

  ......
}

在这个函数中建立了Thread对象,而后调用了Thread::Init函数,在这个函数中建立了当前线程的JNIEnv。

Thread::Init函数的源码在文件"art/runtime/thread.cc"文件中,下面是这个函数的源码:

void Thread::Init(ThreadList* thread_list, JavaVMExt* java_vm) {
  ......

  tlsPtr_.jni_env = new JNIEnvExt(this, java_vm);
  
  ......
}

这个函数中建立了JNIEnvExt对象。JNIEnvExt类型继承了JNIEnv类型,能够去"art/runtime/jni_internal.h"文件中查看。

如今回到JNI_CreateJavaVM函数中,Runtime::Create函数执行完后,将执行Runtime::Start函数启动Android运行时,然会调用这两行语句返回建立的Java虚拟机对象和当前线程的JNI环境:

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

Thread::Current函数得到当前线程的对象。

Tread::GetJniEnv()得到当前线程的JNI环境,这个函数的定义在文件"art/runtime/thread-inl.h"中,下面是它的源码:

// JNI methods
JNIEnvExt* GetJniEnv() const {
  return tlsPtr_.jni_env;
}

Runtime::GetJavaVM()函数得到的是Java虚拟机对象,它的定义在文件"art/runtime/runtime.h"中,下面是它的源码:

JavaVMExt* GetJavaVM() const {
  return java_vm_;
}

执行完JNI_CreateJavaVM函数后返回到startVM函数中。

执行完startVM成功启动虚拟机后,将会经过env->CallStaticVoidMethod语句调用"com.android.internal.os.ZygoteInit"这个Java类的main方法,这个Java方法将会启动zygote服务。

关于如何启动zygote服务将另写一篇文章分析。

至此Android5.1源码虚拟机启动过程分析完毕。

相关文章
相关标签/搜索