自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

我們的Java代碼啟動之后,是如何神奇地變成JVM進程的?

開發(fā) 前端
我們就可以來總結一下咱們寫好的 Java 代碼是如何一步一步運行起來的,如何變成一個 JVM 進程在不斷地運行的了。

知識點

今天給大家分享一個知識點,那就是平時我們寫好的 Java 代碼,他是如何運行起來的,以及他運行起來以后是如何變成 JVM 進程的?然后 JVM 進程又是如何運行我們寫的代碼的?

這些問題想必很多寫了很久 Java 的兄弟可能都不太清楚,今天我們就來好好聊聊這些問題。

寫好的 Java 代碼,他是如何運行起來的?

首先,咱們平時開發(fā)一個 Java 系統(tǒng),其實說白了就是在自己本地的 Intellij IDEA 里寫一大堆的 Java 代碼。

這些 Java 代碼其實都是一些后綴為 .java 的文件,咱們寫好的 Java 代碼都是存放在這些 .java 后綴的文件里的,本質(zhì)跟我們用 word 寫一個后綴為 .doc 的文檔沒啥區(qū)別。

如下圖:

接著呢,假設你已經(jīng)寫好了一些代碼,現(xiàn)在想把代碼運行起來了,此時就應該要先做一個事情,那就是編譯。

這個編譯的話,意思就是說,你寫好的 Java 代碼,咱們的計算機是看不懂的,必須得把寫好的代碼編譯成計算機能看懂的機器語言,就是字節(jié)碼,所以這個時候我們就得先做編譯這個動作。

當然平時你要是用 Intellij IDEA 的話,其實他自動就給你把代碼編譯好了,編譯好的字節(jié)碼文件就是 .class 后綴的。

如下圖:

接著呢,最關鍵的點來了,如果你是自己要運行代碼,可以在命令行里對 .class 字節(jié)碼文件發(fā)出 java 命令,如果你是用 Intellij IDEA 的,那么你點擊運行代碼按鈕,人家自動就給你先編譯代碼,然后他自己直接用 java 命令來運行 .class 字節(jié)碼文件了。

如下圖:

他運行起來以后是如何變成 JVM 進程的?

此時 java 命令一旦發(fā)出,直接就會啟動一個 JVM 進程,所以說,JVM 進程就是這么來的。

大家要注意,你任何 Java 類系統(tǒng)的運行都離不開 JVM 進程,當你用 java 命令運行你的代碼的時候,就一定會啟動一個 JVM 進程,接下來的事兒,就得交給這個 JVM 進程了。

如下圖:

接著下一步,這個 JVM 進程必須要干一個事情,那就是類加載,就是說他必須得把我們寫好的類一各一個加載到內(nèi)存里來,然后包括加載我們的 .class 字節(jié)碼指令,接著才能運行我們寫的代碼。

這個時候第一個要加載的類就是包含 main 方法的主類,這個類就會第一個被加載到內(nèi)存里來,同時這個類里的字節(jié)碼指令也都是要開始被執(zhí)行的。

如下圖:

因此這個時候 JVM 有兩個東西就可以引出來了,一個是方法區(qū),或者現(xiàn)在 Java 新版本也可以叫做元數(shù)據(jù)區(qū),就是這個區(qū)域是存放我們加載到內(nèi)存里的類的。

另外一個是程序計數(shù)器,就是這個東西是存放我們要運行的下一條字節(jié)碼指令的,有人可能會說,這個字節(jié)碼指令是什么?

你大概可以認為,字節(jié)碼指令就是我們的方法里寫的代碼,這些代碼會轉化為字節(jié)碼指令,通過字節(jié)碼指令運行我們的代碼邏輯。

如下圖:

給大家一點稍微形象點的例子,大家看下面一個包含 main 方法的類的代碼:

public class Application {     
public static void main(String[] args) {
// 一大堆的代碼
}
}

JVM 進程又是如何運行我們寫的代碼的?

那所以當我們的 JVM 進程啟動之后,針對這個 Application 類,是不是得加載出來扔進自己的方法區(qū)這個內(nèi)存區(qū)域里?然后接著 JVM 進程是不是得執(zhí)行 main 方法里一行一行的代碼?怎么執(zhí)行代碼?

代碼編譯的時候都搞成字節(jié)碼指令了,這個時候就得通過程序計數(shù)器去引用一條一條的字節(jié)碼指令,然后通過 CPU 去運行每條指令,就等于是在運行我們的每一行代碼了。

如下圖:

接著呢在字節(jié)碼指令運行的過程中,可能會發(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)的局部變量,這種變量人家代碼指令在運行期間,是會扔到一個地方叫做棧內(nèi)存里去的。

這個棧內(nèi)存就是放你的方法代碼運行期間的局部變量的,然后你用 new User() 創(chuàng)建的對象呢?

這種對象是放到堆內(nèi)存里去的,這個堆內(nèi)存是專門放對象的,而且棧內(nèi)存里的變量會指向堆內(nèi)存里的對象。

如下圖:

最后一個概念就是線程,JVM 進程實際上會默認開啟一個 main 線程來運行 main 方法里的代碼,也就是 main 方法里的字節(jié)碼指令。

另外你也可以在代碼中開啟別的線程的并發(fā)運行別的代碼了,所以其實還應該引入一個線程執(zhí)行代碼的概念。

如下圖:

總結

到此為止,我們就可以來總結一下咱們寫好的 Java 代碼是如何一步一步運行起來的,如何變成一個 JVM 進程在不斷地運行的了。

首先我們的 Java 代碼得編譯成字節(jié)碼,其次我們得用 java 命令啟動一個 JVM 進程,接著 JVM 進程會加載我們寫好的類到方法區(qū)里去,同時還會啟動一個默認的 main 線程,通過程序計數(shù)器去指向我們的 main 方法里的一條一條的指令,通過 CPU 來運行指令。

接著我們方法的代碼指令運行期間,對于局部變量都會扔棧內(nèi)存里去,對于創(chuàng)建的對象就會扔堆內(nèi)存里去。

隨著一個方法運行完畢,就會把這個方法的變量從棧內(nèi)存里清理掉,然后方法運行期間創(chuàng)建的對象在堆內(nèi)存里就沒人引用了,此時過一段時間以后也會被 JVM 的一個垃圾回收線程給回收掉這些沒人用的對象,這就是咱們的 JVM 運行原理了。

責任編輯:武曉燕 來源: 石杉的架構筆記
相關推薦

2024-09-10 08:39:48

JVMJava程序

2018-09-07 18:14:37

2023-10-07 08:41:42

JavaJVM

2012-09-25 09:14:28

旁觀者效應負面效應代碼

2022-05-24 06:07:48

JShack用戶代碼

2022-07-05 21:53:26

記錄圖片WebP

2021-09-01 09:54:10

IP地址域名

2022-10-29 17:34:18

JVMJava

2009-06-25 09:11:47

Java之父GoogleJava

2022-04-21 15:28:56

數(shù)據(jù)安全數(shù)據(jù)泄露安全證書

2015-04-01 13:15:04

2012-08-27 09:10:05

JVMJava

2012-12-10 15:12:43

2018-05-15 10:34:50

JavaScript語言互聯(lián)網(wǎng)

2012-07-25 09:15:16

盜版者客戶

2017-04-05 11:10:23

Javascript代碼前端

2021-02-19 08:11:39

Flink Function接口

2022-06-26 23:41:40

人工智能機器算法

2021-09-08 17:16:00

JVM反射 Java

2024-11-21 08:31:07

耗資源神秘進程
點贊
收藏

51CTO技術棧公眾號