国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

(一)線程------JVM體系結構與內存模型概要

2019-11-06 06:07:15
字體:
來源:轉載
供稿:網友

簡述:

    為了徹底搞清楚線程問題,特寫此系列文章記錄之。這一些列文章將講述JVM的體系結構以及涉及線程相關的JVM的運行時數據區來引出java內存模型,Java通信原理將描述線程間數據通信存在的問題以及線程同步的重要性。Java線程狀態講述線程的基本知識。Java線程鎖機制講述線程同步機制的解決辦法。

JVM體系結構

                 

    類加載器:

    每一個被JVM裝載的類型都有一個與之對應的Java.lang.Class類的實例來表示該類型。該實例可以唯一表示被jvm裝載的class類,這個實例和其他類的實例一樣放在堆內存中。

    執行引擎 :

    執行引擎相當于線程,是JVM的核心,執行引擎的作用就是解析JVM字節碼指令,得到執行的結果。執行引擎由各個廠家實現。SUN的hotspot是一種基于棧的執行引擎。而Android的Dalvik是基于寄存器的執行引擎。執行引擎也就是執行一條條代碼的一個流程,代碼都包含在方法體中,執行引擎本質上就是執行一個個方法串起來的流程,對應于操作系統的一個線程,每個java線程就是一個執行引擎的實例。    Java虛擬機的主要任務就是裝在class文件并執行相應的字節碼文件。從JVM體系結構圖中我們看出:一個JVM實例由類裝載器、運行時數據區以及執行引擎所構成。一個Java程序的執行流程為:首先Java源代碼文件(.java后綴)會被Java編譯器編譯為字節碼文件(.class后綴),然后由JVM中的類加載器加載各個類的字節碼文件,加載完畢之后,交由JVM執行引擎執行。那么本系列不會講解類加載器,主要圍繞運行時數據區講解線程相關問題。所以接下來我們就來了解一下運行時數據區(就是JVM內存)。

Java內存模型

    Java代碼是運行在Java虛擬機之上的,由Java虛擬機通過解釋執行(解釋器)或編譯執行(即時編譯器)來完成,故Java內存模型,也就是指Java虛擬機的運行時內存模型。 OK,我們通過一張圖進一步了:                      

    程序計數器

        程序計數器(PRogram Counter Register),也有稱作為PC寄存器。想必學過匯編語言的朋友對程序計數器這個概念并不陌生,在匯編語言中,程序計數器是指CPU中的寄存器,它保存的是程序當前執行的指令的地址(也可以說保存下一條指令的所在存儲單元的地址),當CPU需要執行指令時,需要從程序計數器中得到當前需要執行的指令所在存儲單元的地址,然后根據得到的地址獲取到指令,在得到指令之后,程序計數器便自動加1或者根據轉移指針得到下一條指令的地址,如此循環,直至執行完所有的指令?! ‰m然JVM中的程序計數器并不像匯編語言中的程序計數器一樣是物理概念上的CPU寄存器,但是JVM中的程序計數器的功能跟匯編語言中的程序計數器的功能在邏輯上是等同的,也就是說是用來指示執行哪條指令的?! ∮捎谠贘VM中,多線程是通過線程輪流切換來獲得CPU執行時間的,因此,在任一具體時刻,一個CPU的內核只會執行一條線程中的指令,因此,為了能夠使得每個線程都在線程切換后能夠恢復在切換之前的程序執行位置,每個線程都需要有自己獨立的程序計數器,并且不能互相被干擾,否則就會影響到程序的正常執行次序。因此,可以這么說,程序計數器是每個線程所私有的。  在JVM規范中規定,如果線程執行的是非native方法,則程序計數器中保存的是當前需要執行的指令的地址;如果線程執行的是native方法,則程序計數器中的值是undefined?! ∮捎诔绦蛴嫈灯髦写鎯Φ臄祿伎臻g的大小不會隨程序的執行而發生改變,因此,對于程序計數器是不會發生內存溢出現象(OutOfMemory)的。

   虛擬機棧

  虛擬機棧(Java Vitual Machine Stack),也就是我們常常所說的棧,跟C語言的數據段中的棧類似。事實上,Java棧是Java方法執行的內存模型。為什么這么說呢?下面就來解釋一下其中的原因?! ava棧中存放的是一個個的棧幀,每個棧幀對應一個被調用的方法,在棧幀中包括局部變量表(Local Variables)、操作數棧(Operand Stack)、指向當前方法所屬的類的運行時常量池的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些額外的附加信息。當線程執行一個方法時,就會隨之創建一個對應的棧幀,并將建立的棧幀壓棧。當方法執行完畢之后,便會將棧幀出棧。因此可知,線程當前執行的方法所對應的棧幀必定位于Java棧的頂部。講到這里,大家就應該會明白為什么在使用遞歸方法的時候容易導致棧內存溢出(StackOverFlowError)的現象了以及為什么棧區的空間不用程序員去管理了(當然在Java中,程序員基本不用關系到內存分配和釋放的事情,因為Java有自己的垃圾回收機制),這部分空間的分配和釋放都是由系統自動實施的。對于所有的程序設計語言來說,棧這部分空間對程序員來說是不透明的。虛擬機棧也是線程私有的。

    本地方法棧 :

  本地方法棧與Java棧的作用和原理非常相似。區別只不過是Java棧是為執行Java方法服務的,而本地方法棧則是為執行本地方法(Native Method)服務的。在JVM規范中,并沒有對本地方發展的具體實現方法以及數據結構作強制規定,虛擬機可以自由實現它。在HotSopt虛擬機中直接就把本地方法棧和Java棧合二為一。本地方法棧也是線程私有的。

    堆 :

  在C語言中,堆這部分空間是唯一一個程序員可以管理的內存區域。程序員可以通過malloc函數和free函數在堆上申請和釋放空間。那么在Java中是怎么樣的呢?  Java中的堆是用來存儲對象本身的以及數組(當然,數組引用是存放在Java棧中的)。只不過和C語言中的不同,在Java中,程序員基本不用去關心空間釋放的問題,Java的垃圾回收機制會自動進行處理。因此這部分空間也是Java垃圾收集器管理的主要區域。另外,堆是被所有線程共享的,在JVM中只有一個堆。

   方法區 :

  方法區在JVM中也是一個非常重要的區域,它與堆一樣,是被線程共享的區域。在方法區中,存儲了每個類的信息(包括類的名稱、方法信息、字段信息)、靜態變量、常量以及編譯器編譯后的代碼等。  在Class文件中除了類的字段、方法、接口等描述信息外,還有一項信息是常量池,用來存儲編譯期間生成的字面量和符號引用。 運行時常量池是一個非常重要的部分,它是每一個類或接口的常量池的運行時表示形式,在類和接口被加載到JVM后,對應的運行時常量池就被創建出來。當然并非Class文件常量池中的內容才能進入運行時常量池,在運行期間也可將新的常量放入運行時常量池中,比如String的intern方法?! ≡贘VM規范中,沒有強制要求方法區必須實現垃圾回收。很多人習慣將方法區稱為“永久代”,是因為HotSpot虛擬機以永久代來實現方法區,從而JVM的垃圾收集器可以像管理堆區一樣管理這部分區域,從而不需要專門為這部分設計垃圾回收機制。不過自從JDK7之后,Hotspot虛擬機便將運行時常量池從永久代移除了。

   結論:

     (1)線程私有區,包含以下3類:             程序計數器,記錄正在執行的虛擬機字節碼的地址;             虛擬機棧:方法執行的內存區,每個方法執行時會在虛擬機棧中創建棧幀;             本地方法棧:虛擬機的Native方法執行的內存區;    (2)線程共享區,包含以下2類            Java堆:對象分配內存的區域;            方法區:存放類信息、常量、靜態變量、編譯器編譯后的代碼等數據;            常量池:存放編譯器生成的各種字面量和符號引用,是方法區的一部分。    通過上述的描述,我們把內存模型圖進一步細分如下:                
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 徐汇区| 浦县| 曲周县| 米泉市| 绥滨县| 曲松县| 恩平市| 阿克陶县| 江永县| 虎林市| 集安市| 哈尔滨市| 安平县| 黑龙江省| 文成县| 望奎县| 梁山县| 余姚市| 宜章县| 邳州市| 岐山县| 搜索| 延吉市| 万源市| 榆中县| 湘西| 永清县| 常德市| 霍林郭勒市| 镇康县| 横山县| 浦东新区| 张掖市| 牡丹江市| 二连浩特市| 安义县| 开阳县| 贵南县| 台东市| 河东区| 清河县|