接著來看下JavaMain函式,首先這是一個線程,所以參數類型是void*。進入InitializeJVM,再進入ifn->CreateJavaVM,CreateJavaVM是函式指標,調用hotspot中jni.cpp中的JNI_CreateJavaVM。
注意,JNI_CreateJavaVM為STDCALL,函式自己清空調用堆棧。
_JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args)
一路往下,注意兩個重要變數的賦值,thread::create_vm先跳過。其中,在下圖完成賦值,JNIInvokeInterface_裡面都是一些函式指標。
JNIEnv是一個大結構體,可見主要是對functions賦值,過程如下:
1. 執行上述的Thread::create_vm -> JavaThread* main_thread = new JavaThread() -> initialize() ->set_jni_functions(jni_functions());
2. jni_functions返回jni_NativeInterface,jni_NativeInterface是在jni.cpp中的一個結構體。
3. set_jni_functions完成設置。
回到JavaMain,接著調用LoadMainClass,會加在LauncherHelper.java中的checkAndLoadMain方法。之後就是hotspot層面的一些工作:GetStaticMethodID、CallStaticMethodID,這些都是宏,比較難跟蹤,舉一個例子說明。
1. 最終會調get_method_id,之前的宏採用預處理一下,僅編譯JNI.cpp(gcc工程自行修改,這裡用Visual Studio 2010)。
2. 預處理後的代碼:
3. 最後調用LEAVE()這個宏,銷毀虛擬機的一些工作。
4. Thread::create_vm較複雜,有興趣的自己分析。