摘要:假設源代碼目錄為函數函數在,它處理完命令行參數后跳轉到函數處理命令行選項函數在,它調用加載這個就是編譯的產出在系統下在使用加載動態庫并獲取函數入口地址在系統下在熟悉的同學,對下面的代碼應該會感到很親切創建對象,并將控制流跳轉到呵呵,在
假設 openjdk 源代碼目錄為 jdk9dev
main函數main 函數在 jdk9dev/jdk/src/java.base/share/native/launcher/main.c,它處理完命令行參數后跳轉到 JLI_Launch 函數
int main(int argc, char** argv) { // 處理命令行選項 ... return JLI_Launch(margc, margv, sizeof(const_jargs) / sizeof(char *), const_jargs, appclassc, const_appclasspath, VERSION_STRING, DOT_VERSION, (const_progname != NULL) ? const_progname : *margv, (const_launcher != NULL) ? const_launcher : *margv, HAS_JAVA_ARGS, const_cpwildcard, const_javaw, const_ergo_class); }JLI_Launch
JLI_Launch 函數在 jdk9dev/jdk/src/java.base/share/native/libjli/java.c,
它調用 LoadJavaVM 加載 libjvm.dylib , 這個 libjvm.dylib 就是 hotspot 編譯的產出!
int JLI_Launch(...) { ... if (!LoadJavaVM(jvmpath, &ifn)) { return (6); } ... return JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret); }LoadJavaVM
在 mac osx 系統下 LoadJavaVM 在 jdk9dev/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c
jboolean LoadJavaVM(const char* jvmpath, InvocationFunctions* ifn) { ... #ifndef STATIC_BUILD libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL); #else libjvm = dlopen(NULL, RTLD_FIRST); #endif ifn->CreateJavaVM = (CreateJavaVM_t) dlsym(libjvm, "JNI_CreateJavaVM"); if (ifn->CreateJavaVM == NULL) { JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); return JNI_FALSE; } ... }
使用 dlopen 加載動態庫并獲取 JNI_CreateJavaVM 函數入口地址
JVMInit在 mac osx 系統下 JVMInit 在jdk9dev/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c
熟悉 objc 的同學,對下面的代碼應該會感到很親切:
int JVMInit(InvocationFunctions* ifn, jlong threadStackSize, ...) { ... NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; { JavaLaunchHelper* launcher = [[[JavaLaunchHelper alloc] init] autorelease]; [launcher performSelectorOnMainThread:@selector(launchJava:) withObject:[NSValue valueWithPointer:(void*)&args] waitUntilDone:YES]; rslt = [launcher getReturnValue]; } [pool drain]; return rslt; ... }
創建 JavaLaunchHelper 對象,并將控制流跳轉到 launchJava
@implementation JavaLauncherHelper -(int) launchJava:(NSValue*) argsValue { _returValue = JavaMain([argsValue pointerValue]); } @end
呵呵,在 objc 環境短暫停留后控制留又回到 c/c++ 的世界-JavaMain
JavaMainJavaMain 函數在 jdk9dev/jdk/src/java.base/share/native/libjli/java.c,
在 JavaMain 函數中 會初始化 java 虛擬機,查找 main class,獲取 main class 的 main 方法,并開始執行 java 字節碼
int JNICALL JavaMain(void* _args) { ... // 初始化 jvm if (!InitializeJVM(&vm, &env, &ifn)) { ... } ... // 加載 main class mainClass = LoadMainClass(env, mode, what); ... // 獲取 main 方法 mainID = (*env)->GetStaticMethodID(env, mainClass, "main", "([Ljava/lang/String;)V"); ... // 調用 main 方法 (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs); LEAVE(); }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/65888.html
摘要:準備工作假設源代碼目錄為編譯時啟用了解釋器參考編譯和調試調用棧先在函數參考虛擬機入口中設斷點,然后在的方法中設置斷點通過宏獲取當前,然后創建第個棧幀,然后進入解釋執行字節碼 準備工作 假設 openjdk 源代碼目錄為 jdk9dev 編譯 openjdk 時啟用了 zero 解釋器(參考 OpenJDK9 Hotspot Mac OSX 編譯和調試) 調用棧 先在 JavaMai...
摘要:前言語言可以精確控制對象內存分配,出于性能考慮框架系統程序基本都會自己造輪子開發各種內存管理模塊也不例外,它通過和方法的訪問級別以及重載和方法來管理虛擬機內部對象的內存內存管理相關的基類定義了幾個基類來作為大部分對象的基類顧名思義,它們只能 前言 C++ 語言可以精確控制對象內存分配,出于性能考慮 C++ 框架 or 系統程序基本都會自己 造輪子 開發各種內存管理模塊. hotspot...
摘要:前言本文從類的方法的內部實現入手,分析多線程相關的數據結構類和原理類方法類的方法用于啟動線程,方法內部調用了方法在源代碼中搜索,可以看到對應函數在源代碼中搜索函數核心代碼計算線程堆棧大小創建對象初始化啟動線程在創建時傳入了一個函數指針, 前言 本文從 Java Thread 類的 start 方法的內部實現入手,分析 Hotspot JVM 多線程相關的數據結構(類)和原理 Threa...
摘要:占用率太高,還出各種奇怪問題,轉投調試安裝下載源代碼漫長等待,中間無數次中斷安裝安裝可選如果要使用解釋器,需要安裝設置調試級別,設成可以提供更多的調試信息設置路徑 Intellij CLion CPU 占用率太高,還出各種奇怪問題,轉投 Xcode 調試 hotspot 安裝 hg # brew install hg 下載 open jdk 9 源代碼 # hg clone http...
摘要:前言網上各路大神總結過各種關于內部實現,看別人的文章總覺得不過癮,所以有了這篇文章,嘗試再扒一次的底褲數據結構在分析源代碼之前需要了解相關概念,比如等,參考網絡上各種解說或者之前系列文章,這里重點介紹一下,,每個在內部都有一個的對象與之對應 前言 網上各路大神總結過各種關于 hotspot jvm synchronized 內部實現,看別人的文章總覺得不過癮,所以有了這篇文章,嘗試再扒...
閱讀 1334·2021-11-11 11:00
閱讀 3064·2021-09-24 09:47
閱讀 4989·2021-09-22 15:53
閱讀 971·2021-09-10 10:50
閱讀 3214·2021-09-01 11:40
閱讀 1174·2019-08-30 15:55
閱讀 480·2019-08-30 12:49
閱讀 1059·2019-08-29 17:12