新聞中心
知識(shí)點(diǎn)
今天給大家分享一個(gè)知識(shí)點(diǎn),那就是平時(shí)我們寫(xiě)好的 Java 代碼,他是如何運(yùn)行起來(lái)的,以及他運(yùn)行起來(lái)以后是如何變成 JVM 進(jìn)程的?然后 JVM 進(jìn)程又是如何運(yùn)行我們寫(xiě)的代碼的?

10年的蘿北網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開(kāi)發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。全網(wǎng)營(yíng)銷(xiāo)推廣的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整蘿北建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無(wú)論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)從事“蘿北網(wǎng)站設(shè)計(jì)”,“蘿北網(wǎng)站推廣”以來(lái),每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
這些問(wèn)題想必很多寫(xiě)了很久 Java 的兄弟可能都不太清楚,今天我們就來(lái)好好聊聊這些問(wèn)題。
寫(xiě)好的 Java 代碼,他是如何運(yùn)行起來(lái)的?
首先,咱們平時(shí)開(kāi)發(fā)一個(gè) Java 系統(tǒng),其實(shí)說(shuō)白了就是在自己本地的 Intellij IDEA 里寫(xiě)一大堆的 Java 代碼。
這些 Java 代碼其實(shí)都是一些后綴為 .java 的文件,咱們寫(xiě)好的 Java 代碼都是存放在這些 .java 后綴的文件里的,本質(zhì)跟我們用 word 寫(xiě)一個(gè)后綴為 .doc 的文檔沒(méi)啥區(qū)別。
如下圖:
接著呢,假設(shè)你已經(jīng)寫(xiě)好了一些代碼,現(xiàn)在想把代碼運(yùn)行起來(lái)了,此時(shí)就應(yīng)該要先做一個(gè)事情,那就是編譯。
這個(gè)編譯的話,意思就是說(shuō),你寫(xiě)好的 Java 代碼,咱們的計(jì)算機(jī)是看不懂的,必須得把寫(xiě)好的代碼編譯成計(jì)算機(jī)能看懂的機(jī)器語(yǔ)言,就是字節(jié)碼,所以這個(gè)時(shí)候我們就得先做編譯這個(gè)動(dòng)作。
當(dāng)然平時(shí)你要是用 Intellij IDEA 的話,其實(shí)他自動(dòng)就給你把代碼編譯好了,編譯好的字節(jié)碼文件就是 .class 后綴的。
如下圖:
接著呢,最關(guān)鍵的點(diǎn)來(lái)了,如果你是自己要運(yùn)行代碼,可以在命令行里對(duì) .class 字節(jié)碼文件發(fā)出 java 命令,如果你是用 Intellij IDEA 的,那么你點(diǎn)擊運(yùn)行代碼按鈕,人家自動(dòng)就給你先編譯代碼,然后他自己直接用 java 命令來(lái)運(yùn)行 .class 字節(jié)碼文件了。
如下圖:
他運(yùn)行起來(lái)以后是如何變成 JVM 進(jìn)程的?
此時(shí) java 命令一旦發(fā)出,直接就會(huì)啟動(dòng)一個(gè) JVM 進(jìn)程,所以說(shuō),JVM 進(jìn)程就是這么來(lái)的。
大家要注意,你任何 Java 類(lèi)系統(tǒng)的運(yùn)行都離不開(kāi) JVM 進(jìn)程,當(dāng)你用 java 命令運(yùn)行你的代碼的時(shí)候,就一定會(huì)啟動(dòng)一個(gè) JVM 進(jìn)程,接下來(lái)的事兒,就得交給這個(gè) JVM 進(jìn)程了。
如下圖:
接著下一步,這個(gè) JVM 進(jìn)程必須要干一個(gè)事情,那就是類(lèi)加載,就是說(shuō)他必須得把我們寫(xiě)好的類(lèi)一各一個(gè)加載到內(nèi)存里來(lái),然后包括加載我們的 .class 字節(jié)碼指令,接著才能運(yùn)行我們寫(xiě)的代碼。
這個(gè)時(shí)候第一個(gè)要加載的類(lèi)就是包含 main 方法的主類(lèi),這個(gè)類(lèi)就會(huì)第一個(gè)被加載到內(nèi)存里來(lái),同時(shí)這個(gè)類(lèi)里的字節(jié)碼指令也都是要開(kāi)始被執(zhí)行的。
如下圖:
因此這個(gè)時(shí)候 JVM 有兩個(gè)東西就可以引出來(lái)了,一個(gè)是方法區(qū),或者現(xiàn)在 Java 新版本也可以叫做元數(shù)據(jù)區(qū),就是這個(gè)區(qū)域是存放我們加載到內(nèi)存里的類(lèi)的。
另外一個(gè)是程序計(jì)數(shù)器,就是這個(gè)東西是存放我們要運(yùn)行的下一條字節(jié)碼指令的,有人可能會(huì)說(shuō),這個(gè)字節(jié)碼指令是什么?
你大概可以認(rèn)為,字節(jié)碼指令就是我們的方法里寫(xiě)的代碼,這些代碼會(huì)轉(zhuǎn)化為字節(jié)碼指令,通過(guò)字節(jié)碼指令運(yùn)行我們的代碼邏輯。
如下圖:
給大家一點(diǎn)稍微形象點(diǎn)的例子,大家看下面一個(gè)包含 main 方法的類(lèi)的代碼:
public class Application {
public static void main(String[] args){
// 一大堆的代碼
}
}JVM 進(jìn)程又是如何運(yùn)行我們寫(xiě)的代碼的?
那所以當(dāng)我們的 JVM 進(jìn)程啟動(dòng)之后,針對(duì)這個(gè) Application 類(lèi),是不是得加載出來(lái)扔進(jìn)自己的方法區(qū)這個(gè)內(nèi)存區(qū)域里?然后接著 JVM 進(jìn)程是不是得執(zhí)行 main 方法里一行一行的代碼?怎么執(zhí)行代碼?
代碼編譯的時(shí)候都搞成字節(jié)碼指令了,這個(gè)時(shí)候就得通過(guò)程序計(jì)數(shù)器去引用一條一條的字節(jié)碼指令,然后通過(guò) CPU 去運(yùn)行每條指令,就等于是在運(yùn)行我們的每一行代碼了。
如下圖:
接著呢在字節(jié)碼指令運(yùn)行的過(guò)程中,可能會(huì)發(fā)現(xiàn)你的方法里會(huì)有一些局部變量,同時(shí)還會(huì)創(chuàng)建一些對(duì)象,局部變量會(huì)引用你創(chuàng)建出來(lái)的對(duì)象。
具體代碼可能類(lèi)似于下面這樣子,大家參考一下:
public class Application {
public static void main(String[] args){
User user = new User();
}
}這個(gè)時(shí)候會(huì)發(fā)生什么事情呢?也很簡(jiǎn)單,對(duì)于那個(gè) User user,這是一個(gè)方法內(nèi)的局部變量,這種變量人家代碼指令在運(yùn)行期間,是會(huì)扔到一個(gè)地方叫做棧內(nèi)存里去的。
這個(gè)棧內(nèi)存就是放你的方法代碼運(yùn)行期間的局部變量的,然后你用 new User() 創(chuàng)建的對(duì)象呢?
這種對(duì)象是放到堆內(nèi)存里去的,這個(gè)堆內(nèi)存是專(zhuān)門(mén)放對(duì)象的,而且棧內(nèi)存里的變量會(huì)指向堆內(nèi)存里的對(duì)象。
如下圖:
最后一個(gè)概念就是線程,JVM 進(jìn)程實(shí)際上會(huì)默認(rèn)開(kāi)啟一個(gè) main 線程來(lái)運(yùn)行 main 方法里的代碼,也就是 main 方法里的字節(jié)碼指令。
另外你也可以在代碼中開(kāi)啟別的線程的并發(fā)運(yùn)行別的代碼了,所以其實(shí)還應(yīng)該引入一個(gè)線程執(zhí)行代碼的概念。
如下圖:
總結(jié)
到此為止,我們就可以來(lái)總結(jié)一下咱們寫(xiě)好的 Java 代碼是如何一步一步運(yùn)行起來(lái)的,如何變成一個(gè) JVM 進(jìn)程在不斷地運(yùn)行的了。
首先我們的 Java 代碼得編譯成字節(jié)碼,其次我們得用 java 命令啟動(dòng)一個(gè) JVM 進(jìn)程,接著 JVM 進(jìn)程會(huì)加載我們寫(xiě)好的類(lèi)到方法區(qū)里去,同時(shí)還會(huì)啟動(dòng)一個(gè)默認(rèn)的 main 線程,通過(guò)程序計(jì)數(shù)器去指向我們的 main 方法里的一條一條的指令,通過(guò) CPU 來(lái)運(yùn)行指令。
接著我們方法的代碼指令運(yùn)行期間,對(duì)于局部變量都會(huì)扔棧內(nèi)存里去,對(duì)于創(chuàng)建的對(duì)象就會(huì)扔堆內(nèi)存里去。
隨著一個(gè)方法運(yùn)行完畢,就會(huì)把這個(gè)方法的變量從棧內(nèi)存里清理掉,然后方法運(yùn)行期間創(chuàng)建的對(duì)象在堆內(nèi)存里就沒(méi)人引用了,此時(shí)過(guò)一段時(shí)間以后也會(huì)被 JVM 的一個(gè)垃圾回收線程給回收掉這些沒(méi)人用的對(duì)象,這就是咱們的 JVM 運(yùn)行原理了。
當(dāng)前文章:工作3年的程序員出去面試,結(jié)果連JVM怎么運(yùn)行都不知道
文章轉(zhuǎn)載:http://m.5511xx.com/article/dpedhep.html


咨詢(xún)
建站咨詢(xún)
