新聞中心
知識點(diǎn)
這些問題想必很多寫了很久 Java 的兄弟可能都不太清楚,今天我們就來好好聊聊這些問題。

黃陂ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18982081108(備注:SSL證書合作)期待與您的合作!
寫好的 Java 代碼,他是如何運(yùn)行起來的?
首先,咱們平時開發(fā)一個 Java 系統(tǒng),其實(shí)說白了就是在自己本地的 Intellij IDEA 里寫一大堆的 Java 代碼。
這些 Java 代碼其實(shí)都是一些后綴為 .java 的文件,咱們寫好的 Java 代碼都是存放在這些 .java 后綴的文件里的,本質(zhì)跟我們用 word 寫一個后綴為 .doc 的文檔沒啥區(qū)別。
如下圖:
接著呢,假設(shè)你已經(jīng)寫好了一些代碼,現(xiàn)在想把代碼運(yùn)行起來了,此時就應(yīng)該要先做一個事情,那就是編譯。
這個編譯的話,意思就是說,你寫好的 Java 代碼,咱們的計算機(jī)是看不懂的,必須得把寫好的代碼編譯成計算機(jī)能看懂的機(jī)器語言,就是字節(jié)碼,所以這個時候我們就得先做編譯這個動作。
當(dāng)然平時你要是用 Intellij IDEA 的話,其實(shí)他自動就給你把代碼編譯好了,編譯好的字節(jié)碼文件就是 .class 后綴的。
如下圖:
接著呢,最關(guān)鍵的點(diǎn)來了,如果你是自己要運(yùn)行代碼,可以在命令行里對 .class 字節(jié)碼文件發(fā)出 java 命令,如果你是用 Intellij IDEA 的,那么你點(diǎn)擊運(yùn)行代碼按鈕,人家自動就給你先編譯代碼,然后他自己直接用 java 命令來運(yùn)行 .class 字節(jié)碼文件了。
如下圖:
他運(yùn)行起來以后是如何變成 JVM 進(jìn)程的?
此時 java 命令一旦發(fā)出,直接就會啟動一個 JVM 進(jìn)程,所以說,JVM 進(jìn)程就是這么來的。
大家要注意,你任何 Java 類系統(tǒng)的運(yùn)行都離不開 JVM 進(jìn)程,當(dāng)你用 java 命令運(yùn)行你的代碼的時候,就一定會啟動一個 JVM 進(jìn)程,接下來的事兒,就得交給這個 JVM 進(jìn)程了。
如下圖:
接著下一步,這個 JVM 進(jìn)程必須要干一個事情,那就是類加載,就是說他必須得把我們寫好的類一各一個加載到內(nèi)存里來,然后包括加載我們的 .class 字節(jié)碼指令,接著才能運(yùn)行我們寫的代碼。
這個時候第一個要加載的類就是包含 main 方法的主類,這個類就會第一個被加載到內(nèi)存里來,同時這個類里的字節(jié)碼指令也都是要開始被執(zhí)行的。
如下圖:
因此這個時候 JVM 有兩個東西就可以引出來了,一個是方法區(qū),或者現(xiàn)在 Java 新版本也可以叫做元數(shù)據(jù)區(qū),就是這個區(qū)域是存放我們加載到內(nèi)存里的類的。
另外一個是程序計數(shù)器,就是這個東西是存放我們要運(yùn)行的下一條字節(jié)碼指令的,有人可能會說,這個字節(jié)碼指令是什么?
你大概可以認(rèn)為,字節(jié)碼指令就是我們的方法里寫的代碼,這些代碼會轉(zhuǎn)化為字節(jié)碼指令,通過字節(jié)碼指令運(yùn)行我們的代碼邏輯。
如下圖:
給大家一點(diǎn)稍微形象點(diǎn)的例子,大家看下面一個包含 main 方法的類的代碼:
public class Application {
public static void main(String[] args) {
// 一大堆的代碼
}
}
JVM 進(jìn)程又是如何運(yùn)行我們寫的代碼的?
那所以當(dāng)我們的 JVM 進(jìn)程啟動之后,針對這個 Application 類,是不是得加載出來扔進(jìn)自己的方法區(qū)這個內(nèi)存區(qū)域里?然后接著 JVM 進(jìn)程是不是得執(zhí)行 main 方法里一行一行的代碼?怎么執(zhí)行代碼?
代碼編譯的時候都搞成字節(jié)碼指令了,這個時候就得通過程序計數(shù)器去引用一條一條的字節(jié)碼指令,然后通過 CPU 去運(yùn)行每條指令,就等于是在運(yùn)行我們的每一行代碼了。
如下圖:
接著呢在字節(jié)碼指令運(yùn)行的過程中,可能會發(fā)現(xiàn)你的方法里會有一些局部變量,同時還會創(chuàng)建一些對象,局部變量會引用你創(chuàng)建出來的對象。
具體代碼可能類似于下面這樣子,大家參考一下:
public class Application {
public static void main(String[] args) {
User user = new User();
}
}這個時候會發(fā)生什么事情呢?也很簡單,對于那個 User user,這是一個方法內(nèi)的局部變量,這種變量人家代碼指令在運(yùn)行期間,是會扔到一個地方叫做棧內(nèi)存里去的。
這個棧內(nèi)存就是放你的方法代碼運(yùn)行期間的局部變量的,然后你用 new User() 創(chuàng)建的對象呢?
這種對象是放到堆內(nèi)存里去的,這個堆內(nèi)存是專門放對象的,而且棧內(nèi)存里的變量會指向堆內(nèi)存里的對象。
如下圖:
最后一個概念就是線程,JVM 進(jìn)程實(shí)際上會默認(rèn)開啟一個 main 線程來運(yùn)行 main 方法里的代碼,也就是 main 方法里的字節(jié)碼指令。
另外你也可以在代碼中開啟別的線程的并發(fā)運(yùn)行別的代碼了,所以其實(shí)還應(yīng)該引入一個線程執(zhí)行代碼的概念。
如下圖:
總結(jié)
到此為止,我們就可以來總結(jié)一下咱們寫好的 Java 代碼是如何一步一步運(yùn)行起來的,如何變成一個 JVM 進(jìn)程在不斷地運(yùn)行的了。
首先我們的 Java 代碼得編譯成字節(jié)碼,其次我們得用 java 命令啟動一個 JVM 進(jìn)程,接著 JVM 進(jìn)程會加載我們寫好的類到方法區(qū)里去,同時還會啟動一個默認(rèn)的 main 線程,通過程序計數(shù)器去指向我們的 main 方法里的一條一條的指令,通過 CPU 來運(yùn)行指令。
接著我們方法的代碼指令運(yùn)行期間,對于局部變量都會扔棧內(nèi)存里去,對于創(chuàng)建的對象就會扔堆內(nèi)存里去。
隨著一個方法運(yùn)行完畢,就會把這個方法的變量從棧內(nèi)存里清理掉,然后方法運(yùn)行期間創(chuàng)建的對象在堆內(nèi)存里就沒人引用了,此時過一段時間以后也會被 JVM 的一個垃圾回收線程給回收掉這些沒人用的對象,這就是咱們的 JVM 運(yùn)行原理了。
新聞標(biāo)題:我們的Java代碼啟動之后,是如何神奇地變成JVM進(jìn)程的?
分享網(wǎng)址:http://www.5511xx.com/article/ccssidd.html


咨詢
建站咨詢
