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

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

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


[TOC]


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

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

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

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类的成员函数。

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");
}

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

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

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

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源码虚拟机启动过程分析完毕。

转载于:https://my.oschina.net/ibuwai/blog/524638

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android虚拟机Dalvik完整源码,宝贵资源,欢迎下载! This directory contains the Dalvik virtual machine and core class library, as well as related tools, libraries, and tests. A note about the licenses and header comments --------------------------------------------- Much of the code under this directory originally came from the Apache Harmony project, and as such contains the standard Apache header comment. Some of the code was written originally for the Android project, and as such contains the standard Android header comment. Some files contain code from both projects. In these cases, the header comment is a combination of the other two, and the portions of the code from Harmony are identified as indicated in the comment. Here is the combined header comment: /* * Copyright (C) The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * ---------- * * Portions of the code surrounded by "// BEGIN Harmony code" and * "// END Harmony code" are copyrighted and licensed separately, as * follows: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ Native SH call bridge --------------------- Native SH call bridge is written by Shin-ichiro KAWASAKI and Contributed to Android by Hitachi, Ltd. and Renesas Solutions Corp.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值