不管你是Java開發還是安卓開發都必須要掌握的虛擬機知識點

  Java虛擬機,如果要詳細講,可以寫成一本書,但今天我的重點是想總結虛擬機的一些基礎的知識點,讓大家對虛擬機的內存空間有一個深刻的認識。

  首先,這裏要說一下一個基本流程,當你的Java代碼寫好了之後,是保存在XX.java文件中,然後因爲要讓計算機識別你寫好的代碼,所以要將文件編譯成XXX.class文件,最後,就是運行這個字節碼文件從而執行你寫的代碼,而編譯和運行的工作都是虛擬機乾的。

 

  正如上圖所示那樣,編譯的時候還是在硬盤中執行的,而運行則是在你計算機的內存中執行的,你可以理解虛擬機把這個字節碼文件拿到內存中運行,而虛擬機此時會在內存中劃分一塊空間塊,這個空間塊就是拿來運行字節碼文件裏的代碼。而我們就是要研究這個由虛擬機劃分的內存空間裏的東西。

  現在依然還有很多人覺得該內存空間裏只有堆內存和棧內存,相信對於很多Java工程師來講這兩塊區域應該很熟悉。實際上,嚴格來講,虛擬機中的內存是劃分爲若干個不同的數據區域,主要5個:堆、方法區、虛擬機棧、本地方法棧和程序計數器。如下圖所示:

 

  而平常我們說的棧內存就是虛擬機棧,虛擬機會在虛擬機棧中會創建一個棧幀,棧幀除了用來調用方法並執行方法的,它裏面還有局部變量表,操作數棧,動態連接和返回地址。

  局部變量表存儲每個變量值,也就是平時在方法內部定義的局部變量以及在調方法時傳的參數,都是存儲在局部變量表裏。當虛擬機把java文件編譯成字節碼文件的時候,會對程序裏的方法進行檢查,然後確定每個方法需要分配的最大局部變量表的容量。

  操作數棧,就是存儲要進行操作的變量,是後入先出的結構棧,跟局部變量表一樣也是在編譯的時候就會確定好它的最大容量。當方法執行的時候,剛開始操作數棧是空的,然後隨着執行的過程中會對操作數元素進行壓棧和彈出。

  返回地址,是確保方法在退出後返回到方法被調用的位置的地址信息。當一個方法在正常退出或異常退出完成後,虛擬機棧中的返回地址就會被拿來恢復它的上層方法執行狀態。

  可能說完這些概念之後還是有點抽象,以下舉個例子你就明白了。這裏寫段代碼: 

                                             

 

  以上這個方法在內存中執行的過程是這樣的:

  1. 假設該方法是寫在Sum.java文件裏,虛擬機對它進行編譯時會去確定好棧幀中局部變量表和操作數棧的容量,然後在創建局部變量表和操作數棧的時候根據這個容量來創建便可。
  2. 然後執行int x = 1的時候其實就是先將常量1壓入操作數棧棧頂,然後再把它彈出棧並且放入到局部變量表索引爲1的位置裏,作爲變量x的值。
  3. 接着int y = 2時也一樣,將常量2壓入操作數棧頂,然後再彈出來並且放入到局部變量表索引爲2的位置裏,作爲y變量的值。
  4. 接着執行int z = x + y時,先將此時局部變量表裏的值1和值2壓入到操作數棧中,此時棧頂是2,底下是1,然後進行加法操作得到值3,然後此時棧頂就是該結果值3,將該值3出棧,存入到局部變量表索引爲3的位置。
  5. 最後執行return z的時候,將局部變量表中的3壓入回操作數棧棧頂,然後將操作數棧棧中的3返回給上層方法。到這裏整個sum方法執行完畢,而佈局變量表和操作數棧也會跟着銷燬。

以上過程如果要畫成圖可以這樣表示:

 

  整個流程圖雖然很長,但結構非常容易理解,要操作的元素都出入操作數棧,而變量值則存按索引位置存到局部變量表裏,請結合上文五點步驟描述來理解此圖。

  最後也可以使用javap 命令來查看該類的字節碼指令,驗證是否像上圖描述的流程一樣執行該方法。這點讀者可自行去確認,這裏就不作講解了。

  堆內存這塊區域則是存放對象實例的,大家應該不陌生了,當堆內存中的對象沒有被引用指向時,就變成了可回收對象,被GC進行垃圾回收。

  方法區,主要存儲類信息(類模板),常量和靜態變量等。

  程序計數器,用來記錄當前線程執行的位置,也就是平時我們在編輯器裏不是會看到一段代碼的左側會有數字記錄每一行嗎,這些行數就是線程用來記錄當前方法執行到哪個位置,這樣CPU在切換回線程時仍然能繼續上一次位置繼續執行。

                               

 

  本地方法棧,和虛擬機棧基本一樣,只是本地方法棧是針對native(本地)方法,當涉及到JNI會使用到本地方法棧。

  相信看到這裏,大家應該對虛擬機內存空間應該有一個較好的認識,這樣在下次寫代碼的時候,可以自己作一個感性的底層想象:

  創建一個對象,並且創建一個變量來指向該對象,Object o = new Object()代碼在內存空間里正如上圖所示。

  關於Java虛擬機的知識就講到這裏,其實還有很多知識沒講,但這些不是本篇的重點,而如果有機會,我也將繼續分享關於Java虛擬機的更深的知識。

 

 

                                                                     

                                                                                     掃一掃  關注我的公衆號

                                                                              這裏有你想看的技術文和深度文

                                                                             歡迎大家來投稿,分享你的文章!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章