久久久久亚洲AV色欲av,国产一区二区18禁止观看,91情侣在线精品国产,久久综合激情网,亚洲毛片99基地性色大全

<nav id="rhu4c"><video id="rhu4c"><span id="rhu4c"></span></video></nav>
      1. <th id="rhu4c"></th>

          <code id="rhu4c"></code><code id="rhu4c"><menu id="rhu4c"><optgroup id="rhu4c"></optgroup></menu></code>

          <pre id="rhu4c"></pre>

          湖北企業(yè)新聞網(wǎng),歡迎您!

          幫助中心 廣告聯(lián)系

          網(wǎng)站關鍵詞: 湖北企業(yè)新聞網(wǎng)

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解!

          來源:時間:2020-11-19 09:22:27 閱讀:-

          什么是JVM

          這個大家都應該很熟悉了吧,JVM不就是虛擬機嗎?

          Java虛擬機本質(zhì)上就是一個程序,當它在命令行上啟動的時候,就開始執(zhí)行保存在某字節(jié)碼文件中的指令。

          JVM可以說離我們既熟悉又陌生,很多朋友可能在工作中接觸不到這塊技術,但是在面試往往被問到(概率還蠻大),被問到了自認倒霉,死記硬背是沒用的,到頭來還是的忘,今天給大家說道說道JVM知識點,我要沒讓你明白算我輸,你可以留言噴我,如果要是可以,你們也給我點個贊成不?


          初識JVM

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          相信這張圖大家都不陌生,這是整個Java體系,其中包括JDK.JRE.JVM三者的關系。

          圖中可以看得出來JRE包含了JVM,JDK包含了JRE。

          從包含的角度就是: JDK是爺爺 JRE是父親 JVM是兒子(如果覺得列子不太恰當)來看圖

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          我們來看代碼:

          public class App {

          private String name;

          private Object object = new Object();

          /***

          * 運算

          */

          public int add() {

          int a = 1;

          int b = 2;

          int c = (a + b) * 100;

          return c;

          }

          /**

          * 程序入口

          */

          public static void main(String[] args) throws InterruptedException {

          App app = new App();

          int result = app.add();

          System.out.println(result);

          }

          }

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          我們運行上述代碼輸出結果是300,雖然這個代碼非常簡單,這個時候已經(jīng)涉及到JVM相關的知識了,在我們學Java基礎的時候老師就告訴我們,Java是跨平臺的,一次編寫到處運行。

          那Java是怎么做到跨平臺的?繼續(xù)看下圖:

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          通過此圖大家就不難發(fā)現(xiàn),我們編譯的App.class文件可以在Windows操作系統(tǒng)運行也可以在Linux系統(tǒng)運行,但是兩個系統(tǒng)底層的操作指令是不一樣的,為了屏蔽底層指令的細節(jié),起到一個跨平臺的作用,JVM功不可沒,我們常說Java是跨平臺還不如說是Jvm跨平臺(JRE運行時跨平臺)。那Jvm虛擬機是怎么跨平臺的?

          JVM底層原理

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          JVM底層由三個系統(tǒng)構成分別是:類加載、運行時數(shù)據(jù)區(qū)、執(zhí)行引擎。

          我們今天重點講解JVM運行時數(shù)據(jù)區(qū)(棧),其他兩塊可以關注我之前和后續(xù)文章。

          我們App.class文件通過類加載子系統(tǒng)從硬盤中讀取文件加載到內(nèi)存中(運行時數(shù)據(jù)區(qū))。

          加載完成之后怎么處理了?(打個比喻 人吃飯 》吃到肚子里》各各器官負責自己工作吸收)

          Stack棧

          先講一下其中的一塊內(nèi)存區(qū)域虛擬機棧,大家都知道棧是數(shù)據(jù)結構,也是線程獨有的區(qū)域,也就是每一個線程都會有自己獨立的棧區(qū)域。我們運行App.java輸出300就靠線程執(zhí)行得來的結果。是哪個線程執(zhí)行的?獲取線程快照:“main線程”

          ?!窋?shù)據(jù)結構》存儲內(nèi)容》先進后出FILO

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          大家都知道每個方法都有自己的局部變量,比如上圖中main方法中的result,add方法中的a b c,那么java虛擬機為了區(qū)分不同方法中局部變量作用域范圍的內(nèi)存區(qū)域,每個方法在運行的時候都會分配一塊獨立的棧幀內(nèi)存區(qū)域,我們試著按上圖中的程序來簡單畫一下代碼執(zhí)行的內(nèi)存活動。

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          執(zhí)行main方法中的第一行代碼是,棧中會分配main()方法的棧幀,并存儲math局部變量,,接著執(zhí)行add()方法,那么棧又會分配add()的棧幀區(qū)域。

          這里的棧存儲數(shù)據(jù)的方式和數(shù)據(jù)結構中學習的棧是一樣的,先進后出。當add()方法執(zhí)行完之后,就會出棧被釋放,也就符合先進后出的特點,后調(diào)用的方法先出棧。

          棧幀

          棧幀內(nèi)部“數(shù)據(jù)結構”主要由這幾個部分組成:局部變量表、操作數(shù)棧、方法出口等信息。

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          說了半天,棧幀到底干嘛用的呀?別急講這個就會涉及到更底層的原理–字節(jié)碼。我們先看下我們上面代碼的字節(jié)碼文件。

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          APP.class文件看著像亂碼,其實每個都是有對應的含義的,oracle官方是有專門的jvm字節(jié)碼指令手冊來查詢每組指令對應的含義的。那我們研究的,當然不是這個。

          jdk有自帶一個javap的命令,可以將上述class文件生成一種更可讀的字節(jié)碼文件。

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          Compiled from "App.java"

          public com.App {

          public com.App();

          Code:

          0: aload_0

          1: invokespecial #1 // Method java/lang/Object."":()V

          4: aload_0

          5: new #2 // class java/lang/Object

          8: dup

          9: invokespecial #1 // Method java/lang/Object."":()V

          12: putfield #3 // Field object:Ljava/lang/Object;

          15: return

          public int add();

          Code:

          0: iconst_1

          1: istore_1

          2: iconst_2

          3: istore_2

          4: iload_1

          5: iload_2

          6: iadd

          7: bipush 100

          9: imul

          10: istore_3

          11: iload_3

          12: ireturn

          public static void main(java.lang.String[]) throws java.lang.InterruptedException;

          Code:

          0: new #4 // class com/App

          3: dup

          4: invokespecial #5 // Method "":()V

          7: astore_1

          8: aload_1

          9: invokevirtual #6 // Method add:()I

          12: istore_2

          13: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;

          16: iload_2

          17: invokevirtual #8 // Method java/io/PrintStream.println:(I)V

          20: return

          }


          此時的jvm指令碼就清晰很多了,大體結構是可以看懂的,類、靜態(tài)變量、構造方法、add()方法、main()方法。

          其中方法中的指令還是有點懵,我們舉add()方法來看一下:

          Code:

          0: iconst_1

          1: istore_1

          2: iconst_2

          3: istore_2

          4: iload_1

          5: iload_2

          6: iadd

          7: bipush 100

          9: imul

          10: istore_3

          11: iload_3

          12: iretu


          這幾行代碼就是對應的我們代碼中add()方法中的四行代碼。大家都知道越底層的代碼,代碼實現(xiàn)的行數(shù)越多,因為他會包含一些java代碼在運行時底層隱藏的一些細節(jié)原理。

          那么一樣的,這個jvm指令官方也是有手冊可以查閱的,網(wǎng)上也有很多翻譯版本,大家如果想了解可自行百度。

          執(zhí)行流程

          設計代碼中的部分指令含義:

          第一步:壓棧

          將int類型常量1壓入操作數(shù)棧

          0: iconst_1

          就是將1壓入操作數(shù)棧

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          更正:執(zhí)行流程過程中灰色背景“操作數(shù)?!睉臑椤熬植孔兞勘怼保ǎ。。。。。。。。。。?。

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          第二步:存儲

          將int類型值存入局部變量1

          1: istore_1

          局部變量1,在我們代碼中也就是第一個局部變量a,先給a在局部變量表中分配內(nèi)存,然后將int類型的值,也就是目前唯一的一個1存入局部變量a

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          第三步:賦值

          這兩行代碼就和前兩行類似了。

          2: iconst_2

          3: istore_2

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          第四步:裝載

          從局部變量2中裝載int類型值

          4: iload_1

          5: iload_2

          這兩個代碼是將局部變量1和2,也就是a和b的值裝載到操作數(shù)棧中

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          第五步:加法

          執(zhí)行int類型的加法

          6: iadd

          iadd指令一執(zhí)行,會將操作數(shù)棧中的1和2依次從棧底彈出并相加,然后把運算結果3在壓入操作數(shù)棧底。

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          第六步:壓棧

          將一個8位帶符號整數(shù)壓入棧

          7: bipush 100

          這個指令就是將100壓入棧

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          第七步:乘法

          執(zhí)行int類型的乘法

          9: imul

          這里就類似上面的加法了,將3和100彈出棧,把結果300壓入棧

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          第八步:壓棧

          將將int類型值存入局部變量3

          10: istore_3

          這里大家就不陌生了吧,和第二步第三步是一樣的,將300存入局部變量3,也就是c

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          第九步:裝載

          從局部變量3中裝載int類型值

          11: iload_3

          從局表變量3加載到操作數(shù)棧

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          第十步:返回

          返回int類型值

          12: ireturn

          我們add方法是被main方法中調(diào)用的,所以通過方法出口返回到mian方法中result變量存儲方法出口說白了不就是方法執(zhí)行完了之后要出到哪里,那么我們知道上面add()方法執(zhí)行完之后應該回到main()方法第三行那么當main()方法調(diào)用add()的時候,add()棧幀中的方法出口就存儲了當前要回到的位置,那么當add()方法執(zhí)行完之后,會根據(jù)方法出口中存儲的相關信息回到main()方法的相應位置??次覉D中的紅線

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          棧堆關系

          main方法中除了result變量還有一個app變量,app變量指向的是一個對象。那對象是怎么存儲的?這兒要在說下局表變量表結構:基本類型和引用類型(Java叫引用C C++叫指針)

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          關系就是:

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          通過引用在棧中的app變量引用堆中的App對象

          總結

          講到這兒相信大家對JVM棧執(zhí)行原理是不是熟悉了?如果覺得不錯歡迎點贊評論。

          程序員:JVM虛擬機-棧執(zhí)行原理深入詳解

          推薦閱讀:青海信息港