Android虛擬機的啓動 源碼分析

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java#main()是怎麼執行的 ? 這需要從虛擬機啓動的執行開始說起。

虛擬機啓動的入口從frameworks/base/core/jni/AndroidRuntime.cpp#start方法開始

void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{
	jni_invocation.Init(NULL); //初始化JNI
	JNIEnv* env; //JNI環境指針
	if (startVm(&mJavaVM, &env) != 0) { //啓動一個虛擬機,會給mJavaVM、env賦值
	    return;
	}
	onVmCreated(env); //虛擬機Created
	
	//註冊android的一些函數
	if (startReg(env) < 0) {
	    ALOGE("Unable to register all android natives\n");
	    return;
	}
	//...
	//通過env->FindClass 加載String字符串
	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);
 
 	//className是方法傳參過來的,toSlashClassName是個轉換的方法,把點變成斜槓之類的
	char* slashClassName = toSlashClassName(className); 
	//找到frameworks/base/core/java/com/android/internal/os/ZygoteInit.java這個類
	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"); //找ZygoteInit的main方法,其中jmethodID就是ArtMethod
	        if (startMeth == NULL) {
	            ALOGE("JavaVM unable to find main() in '%s'\n", className);
	            /* keep going */
	        } else {
	            env->CallStaticVoidMethod(startClass, startMeth, strArray); //傳入類、方法、參數,通過反射調用ZygoteInit的main方法
            }
        }
    }
    //...
}

小結

可以看到,Android虛擬機的啓動是在AndroidRuntime.cpp#start()方法。

  1. 首先會初始化JNI
  2. 然後啓動一個虛擬機
  3. 找到ZygoteInit.java這個類
  4. 找ZygoteInit的main方法
  5. 傳入類、方法、參數,通過反射調用ZygoteInit的main方法

其他

源碼爲Android 5.1.0_r3

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章