字節(jié)碼解釋器通過改變這個計算器的值來選擇下一條需要執(zhí)行的字節(jié)碼指令,分支,循環(huán),跳轉(zhuǎn),異常處理,線程恢復(fù),如果執(zhí)行的是Native方法,這個計算器的值則為空。
2. Java虛擬機棧(線程私有)
(1) 是什么
Java虛擬機棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個方法在執(zhí)行的同時都會創(chuàng)建一個棧幀,每個方法從調(diào)用直至執(zhí)行完成的過程,就對應(yīng)著一個棧幀在虛擬機棧中入棧到出棧的過程。
大圖模式 (2) 組成
① 局部變量表
存放了編譯期可知的基本類型、對象引用類型和returnAddress類型(指向一條字節(jié)碼指令的地址。即程序就是存儲在方法區(qū)的字節(jié)碼指令,而 returnAddress 類型的值就是指向特定指令內(nèi)存地址的指針)
② 操作數(shù)棧
操作數(shù)是一個后入先出棧,JVM所有的操作碼都是對操作數(shù)棧上的數(shù)據(jù)進行操作,對于每一個方法的調(diào)用,JVM會建立一個操作數(shù)棧,以供計算使用。
例如 a = b c 的字節(jié)碼執(zhí)行過程中操作數(shù)棧以及局部變量表的變化如下圖所示。
大圖模式 局部變量表中存儲著a、b、c 三個局部變量,首先將b和c分別入棧
大圖模式 ③ 動態(tài)鏈接
運行期間轉(zhuǎn)化為直接引用,就稱為動態(tài)鏈接。Class字節(jié)碼的常量持中存有大量的符號引用,在運行期才將符號引用變成直接引用(也就是指向數(shù)據(jù)),可以是方法或者字段的引用。
④ 方法出口
即本方法執(zhí)行后下一步指令的地址,方法正常退出時,調(diào)用者PC計數(shù)器的值就可以作為返回地址,異常退出時,返回地址是要通過異常處理器來確定。
大圖模式 3. 本地方法棧(線程私有)
(1) 是什么?
保存native方法進入?yún)^(qū)域的地址
4. Java堆(線程共享)
(1) 是什么?
所有的對象實例以及數(shù)組都要在堆上分配。是垃圾收集器管理的主要區(qū)域。
(2) 分區(qū)
① 新生代: Eden區(qū)、Survivor From區(qū)、Survivor To區(qū)
② 老年代
5. 方法區(qū)(線程共享)
(1) 是什么
方法區(qū)用于存儲已被虛擬機加載的類信息、方法、常量、靜態(tài)成員變量、JIT(即時編譯器)編譯后的代碼等數(shù)據(jù),在類加載時分配。
(2) 也叫非堆,分配在元空間
元空間:類的元數(shù)據(jù),如方法數(shù)據(jù)、方法信息(字節(jié)碼,棧和變量大小)、運行時常量池、已確定的符號引用和虛方法表等方法區(qū)的數(shù)據(jù),保存在本地內(nèi)存區(qū)域(堆外內(nèi)存)
6. 運行時常量池(線程共享)
(1) 是什么
運行時常量池用于存放編譯期和運行期生成的各種字面量和符號引用。這部分內(nèi)容將在類加載后進入方法區(qū)的運行時常量池中存放。屬于方法區(qū)的一部分
(2) 字面量和符號引用
字面量:1.字符串;2.基本類型值;3.final常量 符號引用:1.類和方法的全限定名;2.字段的名稱和描述符;3.方法的名稱
二、 Jvm內(nèi)存模型
1. 定義
由于不同平臺內(nèi)存模型的差異,有可能導(dǎo)致程序在不同平臺的并發(fā)訪問出錯。Java內(nèi)存模型(Java Memory Model,JMM)是屏蔽各種硬件和操作系統(tǒng)的內(nèi)存訪問差異,以實現(xiàn)讓Java程序在各種平臺下都能達到一致的內(nèi)存訪問效果。
大圖模式 2. 具體操作
定義程序中各個變量的訪問規(guī)則,即在虛擬機中將變量存儲到內(nèi)存和從內(nèi)存中取出變量的底層細(xì)節(jié)。
此處的變量是指實例字段,靜態(tài)字段和構(gòu)成數(shù)組對象的元素,不包括局部變量與方法參數(shù)
3. 主內(nèi)存和工作內(nèi)存
Jvm內(nèi)存模型規(guī)定所有的變量都存儲在主內(nèi)存中,每條線程還有自己的工作內(nèi)存,工作內(nèi)存保存了被該線程使用到的變量的主內(nèi)存副本拷貝。
大圖模式 4. synchronization、final、volatile
(1) synchronization
① 互斥
對于一個monitor對象,當(dāng)被一個線程持有,其他線程只能等待
② 可見性
保證了線程在同步代碼塊期間寫入動作,對于后續(xù)進入該代碼塊的線程是可見的(持有相同monitor對象的線程)。
當(dāng)前線程釋放monitor對象,作用是把cpu緩存數(shù)據(jù)刷新到主內(nèi)存中;其他線程進入該代碼塊時,需要獲取monitor對象,會使cpu緩存失效,從而使變量從主內(nèi)存中重新加載。