浅析ART虚拟机(一)虚拟机第一次启动

1.前言:

ART是Android上的应用和部分系统服务使用的托管式运行时,ART和前身Dalvik最初是专为Android项目打造的。 每一个APP进程中都有一个ART的虚拟机副本,这些副本都是从zygote中复制过来的,虽然都有,但是对应到实际的物理内存中只存在了一份,这也解释了为什么APP进程的启动为什么需要zygote的copy on write机制。

2.第一个ART虚拟机启动

内核启动后到达用户空间,第一个进程init通过读取init.rc来进行Android世界的初始化,孵化出Android世界的第一个进程zygote,而在zygote中,就初始化了第一个ART虚拟机。

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    socket usap_pool_primary stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    onrestart restart vendor.servicetracker-1-1
    writepid /dev/cpuset/foreground/tasks

对应的源文件就是App_main.cpp,进程名为zygote。

3.zygote中启动ART虚拟机

3.1App_main中
int main(int argc, char* const argv[])
{
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    ...//参数解析
    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.");
    }
}
3.2 AppRuntime->start()既AndroidRuntime->start()

因为AppRuntime继承AndroidRuntime,从注释也可以看到,在创建了虚拟机之后,会调用传过来的zygoteInit.main方法。

/*
 * Start the Android runtime.  This involves starting the virtual machine
 * and calling the "static void main(String[] args)" method in the class
 * named by "className".
 *
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    // className = com.android.internal.os.ZygoteInit
    ...
    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL); //见3.3
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) { // 见3.4
        return;
    }
    onVmCreated(env);

    ...

    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        // 调用com.android.internal.os.ZygoteInit的main方法
        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 {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
}
3.3 jni_invocation.Init(NULL);

虚拟机启动部分,首先进行了init。主要就是确认了虚拟机的3个重要的函数,确认了入口。

bool JniInvocationImpl::Init(const char* library) {
  library = GetLibrary(library, buffer);
  ...
  if (!FindSymbol(reinterpret_cast<FUNC_POINTER*>(&JNI_GetDefaultJavaVMInitArgs_),
                  "JNI_GetDefaultJavaVMInitArgs")) {
    return false;
  }
  if (!FindSymbol(reinterpret_cast<FUNC_POINTER*>(&JNI_CreateJavaVM_),
                  "JNI_CreateJavaVM")) {
    return false;
  }
  if (!FindSymbol(reinterpret_cast<FUNC_POINTER*>(&JNI_GetCreatedJavaVMs_),
                  "JNI_GetCreatedJavaVMs")) {
    return false;
  }
}

其中的getLibrary也就是

static const char* kLibraryFallback = "libart.so";

也就是我们可以通过配置属性来决定当前使用的虚拟机,目前我们使用的也就是art虚拟机了。好的,现在init完成了,让我们回到启动虚拟机.

3.4 startVM()
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
    ...//省略中间的参数配置

    /*
     * Initialize the VM.
     *
     * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.
     * If this call succeeds, the VM is ready, and we can start issuing
     * JNI calls.
     */
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        ALOGE("JNI_CreateJavaVM failed\n");
        return -1;
    }
}

3.5 JNI_CreateJavaVM

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

而此处的JNI_CreateJavaVM_就是在3.3中保存在变量中的入口。也就是libart.so中的JNI_CreateJavaVM函数。