亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

在Java語言中main方法是如何被執行的

發布時間:2021-10-15 14:30:54 來源:億速云 閱讀:190 作者:iii 欄目:web開發

這篇文章主要講解了“在Java語言中main方法是如何被執行的”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“在Java語言中main方法是如何被執行的”吧!

對于Java而言,其底層是Java虛擬機在跑著,也就是JVM,這篇文章如無特殊說明,默認以Hotspot為研究對象。

先來回顧一下那篇文章,對于C/C++程序而言,從創建進程到進入main函數,主要就是經歷了四個階段:

  • 進程 & 主線程創建階段

  • 主線程啟動執行并進行進程級初始化操作(如加載系統動態鏈接庫)

  • 主線程進入可執行文件的入口(OEP)并進行C/C++運行時庫初始化

  • 從C/C++運行時庫調入main函數

你知道的,Java的虛擬機JVM主要是C++編寫的,所以JVM本質上也算是一個C++程序。

因此,上面的四個階段,對于JVM而言,同樣適用。

只不過呢,對于C/C++程序而言,到這里就已經進入main函數了,話題就可以結束了,而對于Java程序,執行到JVM的main,一切才剛剛開始。

JVM的main

故事,要從JVM的main函數開始講起···

你應該知道的,不管你是普通Java程序,還是用的Spring或者其他什么框架,最終的程序都是在一個Java進程中運行的,這個進程的可執行文件就是一個exe(windows上)或者elf(linux上)。

咱們就從這個可執行文件入手,以Linux系統上的Java8版本為例,用反匯編神器IDA打開可以看到,這個可執行文件的入口:

在Java語言中main方法是如何被執行的

和咱們在上一篇分析的流程符合,進入這個程序啟動入口后,會經過一系列的調用,最后來到main函數:

在Java語言中main方法是如何被執行的

反匯編看著好頭大,好在,HotSpot虛擬機有開源版本,咱們可以去OpenJDK中找來這個main函數的源碼瞧瞧。

不同版本差異還是挺大,這里以Java8為例:

代碼路徑:https://github.com/openjdk/jdk/blob/jdk8-b20/jdk/src/share/bin/main.c

在Java語言中main方法是如何被執行的

在這個代碼中除了main函數,還可以看到如果定義了JAVAW宏定義,則入口從main變成了WinMain函數,做過Windows應用程序開發的朋友這個時候應該露出了滿意的微笑。

如果定義了JAVAW,則是一個Win32 GUI的程序,當然在Linux上是肯定沒有這個宏定義的,不過這不是本文的主題。

可以看到main函數只是一個包裝,直接就進入了JLI_Launch中。

這個函數位于同目錄下的隔壁java.c文件中,是JVM非常重要的初始化函數,主要完成了下面幾件事情:

  • 參數解析,環境配置

  • 檢查Java運行環境

  • 加載JVM核心動態庫libjvm.so

  • 創建并初始化Java虛擬機對象

這些過程都不是我們這篇文章探究的目標,咱們繼續把目光聚焦在Java中的main函數是怎么得到調用的。

在JLI_Launch的結尾,調用了ContinueInNewThread,從這個函數的名字我們也能窺探它的作用。

在Java語言中main方法是如何被執行的

這個函數還是一層封裝,內部調用了真正干活的函數ContinueInNewThread0:

在Java語言中main方法是如何被執行的

接下來就是創建線程來繼續后面的事情了,不過創建線程涉及到操作系統API的調用,所以這個函數在不同版本的系統中都有對應的實現。來看傳給它的第一個參數,這是新線程啟動后將要執行的入口函數:JavaMain。

JavaMain

這個函數的名字就有點意思了,看起來,快要進入Java的地界兒了,加油繼續看下去:

int JNICALL  JavaMain(void * _args) {       // ...     // 尋找啟動類     mainClass = LoadMainClass(env, mode, what);     // ...     // 尋找啟動類中的main函數     mainID = (*env)->GetStaticMethodID(env, mainClass, "main",                                        "([Ljava/lang/String;)V");     // ...     // 調用它     (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);     // ... }

JavaMain中的細節挺多的,咱們抽出需要關心的,要調用咱們寫的main方法就像把大象關進冰箱一共三步:

  • 找到啟動類

  • 找到啟動類中的main方法

  • 調用它

具體尋找的過程這里就不展開了,有些繁瑣,但你應該能猜到,Java代碼編譯后都是以class文件的形式存儲的,所以這個尋找的背后少不了要涉及到class類加載等一系列的工作。

總之,一頓操作猛如虎,嘿,JVM把咱們寫的main方法找到了!接下來就是調用它了。

進入Java世界

調用main方法的是CallStaticVoidMethod,從名字可以看到,這是在調用一個靜態的、返回值為空的方法。注意了,C++的地盤快到邊境了,咱們即將通過它來到美麗的Java新世界!

這個函數內部后面會來到:

JavaCalls::call(result, method, &java_args, CHECK);

最終,會創建Java方法棧幀,準備好模板解釋器,隨后轉向解釋器入口開始執行字節碼,正式進入Java世界!

進入Java世界第一站,就是前面找到的啟動類的main方法,在這里開啟程序在Java世界的征程。

感謝各位的閱讀,以上就是“在Java語言中main方法是如何被執行的”的內容了,經過本文的學習后,相信大家對在Java語言中main方法是如何被執行的這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

陆良县| 榆中县| 莎车县| 安庆市| 如皋市| 宿迁市| 洮南市| 土默特右旗| 永清县| 武冈市| 丁青县| 大余县| 乐至县| 丰镇市| 宝山区| 甘孜县| 隆昌县| 略阳县| 普兰店市| 贺州市| 綦江县| 申扎县| 巫山县| 怀安县| 西青区| 旅游| 昌宁县| 茶陵县| 宁波市| 银川市| 奎屯市| 桂阳县| 广灵县| 周至县| 肥西县| 南投县| 铜陵市| 商洛市| 武强县| 郸城县| 呈贡县|