深入理解JVM總結——虛擬機器位元組碼執行引擎
執行引擎是Java虛擬機器最核心的組成部分之一。物理機和虛擬機器都有執行程式碼的能力。區別在於物理機的執行引擎是直接建立在處理器、硬體、指令集和作業系統層面上的,而虛擬機器的執行引擎則是由自己實現的,因此可以自行指定指令集與執行引擎的結構體系,並且能夠執行那些不被硬體直接支援的指令集格式。
虛擬機器執行引擎在執行Java程式碼的時候分為解釋執行(通過直譯器執行)和編譯執行(通過即時編譯器產生原生代碼執行),也可以兩者兼備。
所有的Java虛擬機器的執行引擎都是一致的:輸入的是位元組碼檔案,處理過程是位元組碼解析的等效過程,輸出的是執行結果。
執行時棧幀結構
棧幀,用於支援虛擬機器進行方法呼叫和方法執行的資料結構,是虛擬機器執行時資料區中的虛擬機器棧的棧元素。儲存了方法的區域性變數、運算元棧、動態連線和方法返回地址等資訊。每一個方法從呼叫到執行完成,都對應著一個棧幀在虛擬機器棧中從入棧到出棧的過程
編譯程式碼時,棧幀的記憶體分配已經確定了,不會受到程式執行期變數資料的影響,而僅僅決定於具體的虛擬機器實現。
對於執行引擎來說,在活動執行緒中,只有位於棧頂的棧幀才是有效的,稱為當前棧幀,與之對應的方法稱為當前方法。執行引擎執行的所有位元組碼指令都只針對當前棧幀進行操作。
區域性變量表
是一組變數值儲存空間,用於儲存方法引數和方法內部定義的區域性變數。編譯成Class檔案時,在方法的Code屬性的max_locals確定其最大容量。
區域性變量表的容量已變數槽(Slot)為最小單位。每一個slot都能存放基本資料型別的資料,一般來說就是32位以內。64位虛擬機器則以高位對齊分配兩個連續slot空間(double,long)。對於64位,不允許單獨只訪問其中的一個,不然會在校驗階段拋異常。
方法執行時,虛擬機器使用區域性變量表完成引數值到引數列表的傳遞過程
區域性變量表中的slot還存在關於陣列等物件的引用,即使離開了程式碼的作用域,在此之後若沒有任何堆區域性變量表的讀寫操作的話,該引用原本所佔用的slot還沒有被其他變數所複用,所以作為GCRoots一部分的區域性變數仍保持著對它的關聯。
public statci void main(String[] args){
byte [] a=new byte[64*1024*1024];//作用域在gc之後
/////或者如下,也是沒有將記憶體收回來
{
byte[] a=new byte[64*1024*1024];//出了括號就出了作用域
}
//新增如下程式碼,就變動了區域性變量表,記憶體被真正回收。
int a=0;
System.gc();
}
不使用的物件,佔用大量記憶體,可以手動賦值為null,作用同int a=0那句。
類變數有兩次賦初始值的過程,一次在準備階段,賦予系統初始值;一次在初始化階段,賦予程式猿定義的初始值。因此,即時在初始化階段程式設計師沒有為類變數賦值也無所謂,它仍具有一個確定的初始值。
區域性變數不行,並不是所有都如int ,boolean一樣都有預設初始值,不賦初始值區域性變數是不能使用的。就算編譯通過或手寫位元組碼生成class檔案,位元組碼校驗的時候也會被虛擬機發現而導致類載入失敗。
運算元棧
也作操作棧,後入先出棧。最大深度在編譯時就寫入Code屬性的max_stacks中。運算元棧中每個元素可以是任意Java資料型別,包括long和double。32位資料型別佔容量為1,64位的佔2。在方法執行的任何時候,運算元棧的深度都不會超過max_stacks設定的最大值。
運算元棧中元素資料型別必須與位元組碼指令的序列嚴格匹配,如i指令為iadd,則棧頂兩個都為int的,不能出現long 和float。
在概念模型上,兩個棧幀作為虛擬機器的元素是相互獨立的。但在大多數虛擬機器實現裡都優化處理,兩個棧幀會出現一部分重疊。
Java虛擬機器的解釋執行引擎又稱為“基於棧的執行引擎”的棧就是運算元棧。
動態連線
每個棧幀都包含一個指向執行時常量池中該棧幀所屬方法的引用,持有這個引用是為了支援方法的呼叫過程中的動態連線。
符號引用,一部分在類載入階段或第一次使用時就轉化為直接引用,即靜態解析。而另一部分在執行期間轉化為直接引用,這部分就為動態連線。
方法返回地址
一個方法執行時,只有兩種方式退出方法:一種是執行引擎遇到任意一個方法返回的位元組碼指令,可能會有返回值傳遞給上層的方法呼叫者,是否有返回值和返回值型別將根據遇到何種方法返回指令來決定。這種退出方式稱為正常完成出口。
第二種方式,在方法執行過程中遇到了異常,且異常沒有在方法體內得到處理,無論Java虛擬機器內部產生的異常還是程式碼使用athrow位元組碼指令產生的異常,只要在本方法的異常表中沒有搜尋到匹配的異常處理器,就會導致方法退出。這種退出方式成為異常完成出口。它是不會給上層呼叫者返回任何值的。
方法退出等同於把當前棧出棧,因此退出時可能執行的操作有:恢復上層方法的區域性變量表和運算元。
附加資訊
即棧幀資訊。動態連線、方法返回地址、其他資訊等。
方法呼叫
方法呼叫並不等同於方法執行,方法呼叫階段唯一任務就是確定被呼叫方法的版本(即呼叫的哪一個方法),暫時不涉及方法內部具體的執行過程。一切方法呼叫在class檔案中儲存的都只是符號引用,而不是方法在實際執行時記憶體佈局中的入口地址(直接引用)。給Java帶來強大動態擴充套件能力,也使其變得相對複雜,需要在類載入或是執行期間才能確定目標方法的呼叫。
解析
符號引用轉化直接引用的解析階段的前提:方法在程式真正執行之前就有一個可確定的呼叫版本,且這個方法的呼叫版本在執行期間是不可變的。也就是說呼叫目標在程式程式碼寫好、編譯器進行編譯時就必須確定下來。這類方法的呼叫就稱為解析。
符合這類的有:靜態方法和私有方法兩大類。因為前者和型別直接關聯,而後者在外部不可訪問,由此決定了它們都不可能通過繼承或別的方式重寫其他版本,因此都適合在類載入階段進行解析。
Java虛擬機器,5條呼叫位元組碼指令,
invokestatic,靜態方法
invokespecial(呼叫例項構造器方法、私有方法和父方法),
invokevirtual,虛方法(除上述兩種和final以外的其他方法)
invokeinterface,介面方法,會在執行時再確定一個實現此介面的物件。
invokedynamic(先在執行時動態解析出呼叫點限定符所引用的方法,然後再執行該方法)。
被final修飾的方法,雖然是使用的invokevirtual指令來呼叫,但由於無法覆蓋,沒有其他版本,也無需進行多型選擇,或其選擇結構唯一,因此final也是一種非虛方法。
解析呼叫時一個靜態過程,在編譯期間就已確定,在類裝在的解析階段就會把涉及的符號引用全部阻焊變為可確定的直接引用,不會延遲到執行期再去完成。
分派
分派呼叫則可能是靜態的(編譯期完成)也可能是動態的(執行期完成),根據分派依據的宗量數(方法的呼叫者和方法的引數統稱為方法的宗量)又可分為單分派和多分派。兩類分派方式兩兩組合便構成了靜態單分派、靜態多分派、動態單分派、動態多分派四種分派情況。。
靜態分派
未完待續,P247。
相關推薦
深入理解JVM總結——虛擬機器位元組碼執行引擎
執行引擎是Java虛擬機器最核心的組成部分之一。物理機和虛擬機器都有執行程式碼的能力。區別在於物理機的執行引擎是直接建立在處理器、硬體、指令集和作業系統層面上的,而虛擬機器的執行引擎則是由自己實現的,因此可以自行指定指令集與執行引擎的結構體系,並且能夠執行那些不
[深入理解JVM 六]---虛擬機器位元組碼執行系統
前邊介紹了jvm的執行時記憶體分配,類檔案的結構,以及類載入機制,這樣,一個編譯好的class二進位制位元組碼檔案就已經被載入完畢,等待下一步的執行。接下來分幾個部分來介紹這部分內容。首先方法的呼叫和執行依賴於虛擬機器棧,第一部分詳細介紹一下虛擬機器棧的棧幀結構
深入理解JVM(八)——位元組碼執行引擎
不用虛擬機器,執行引擎在執行Java程式碼時,會有解釋執行(通過直譯器執行)和編譯執行(通過及時編譯器產生原生代碼執行)兩種選擇。 執行時棧幀結構 棧幀用於支援虛擬機器進行方法呼叫和方法執行的資料結構。棧幀儲存了方法的區域性變量表,運算元棧,動態連線和方法返回地址等資訊。每一個方法從
JAVA虛擬機器(JVM)——虛擬機器位元組碼執行引擎(二)
方法呼叫 方法呼叫並不等同於方法執行,方法呼叫階段唯一的任務就是確定呼叫哪一個方法,暫時還不涉及方法內部的具體執行過程。Class檔案的編譯過程中不包含傳統編譯中的連線步驟,一切方法呼叫在C
JAVA虛擬機器學習總結——虛擬機器位元組碼執行引擎
執行時的棧幀結構 棧幀是用於支援虛擬機器進行方法呼叫和方法執行的資料結構,它是虛擬機器執行時資料區中的虛擬機器棧的棧元素。 棧幀儲存了方法的區域性變量表,運算元棧,動態連線和方法返回值等資訊每一個方法從呼叫至執行完成的過程,都對應者棧幀在虛擬機器棧裡面從入找
JVM之虛擬機器位元組碼執行引擎(八)
虛擬機器的執行引擎是自己實現的,有自己的指令集和執行引擎的結構體系,能夠執行那些不被硬體直接支援的指令集格式。(物理機執行引擎是建立在處理器、硬體、指令集和作業系統層面)。 但在不同的虛擬機器實現裡,執行引擎在執行java程式碼的時候,可能會解釋執行和編譯執行
深入理解JVM虛擬機器讀書筆記【第八章】虛擬機器位元組碼執行引擎
8.1 概述 8.2 執行時棧幀結構 8.2.1 區域性變量表 8.2.2 運算元棧 8.2.3 動態連線 8.2.4 方法返回地址
深入理解JVM虛擬機器(七):虛擬機器位元組碼執行引擎
程式碼編譯的結果就是從本地機器碼轉變為位元組碼。我們都知道,編譯器將Java原始碼轉換成位元組碼?那麼位元組碼是如何被執行的呢?這就涉及到了JVM位元組碼執行引擎,執行引擎負責具體的程式碼呼叫及執行過程。就目前而言,所有的執行引擎的基本一致: 輸入:位元組碼檔案
深入理解jvm(四):虛擬機器位元組碼執行引擎
執行時棧幀 每一個方法從呼叫開始到執行完成都對應著一張棧幀的進棧和出棧。棧幀中儲存著區域性變量表,運算元表,動態連結和方法返回地址。位於虛擬機器最頂層的稱為當前方法棧。 區域性變量表 儲存當前方法的區域性變數和引數,區域性變量表的容量以變數槽slo
讀書筆記 ---- 《深入理解Java虛擬機器》---- 第7篇:虛擬機器位元組碼執行引擎
上一篇:虛擬機器類載入機制:https://blog.csdn.net/pcwl1206/article/details/84260914 第7篇:虛擬機器位元組碼執行引擎 執行引擎是Java虛擬機器最核心的組成部分之一。“虛擬機器”是一個相對於“物理機”的概念,這兩種機器都有程式碼執行能力
【深入理解 Java 虛擬機器筆記】虛擬機器位元組碼執行引擎
7.虛擬機器位元組碼執行引擎 執行引擎是 Java 虛擬機器最核心的組成部分之一。在 Java 虛擬機器規範中制定了虛擬機器位元組碼執行引擎的概念模型,這個概念模型成為各種虛擬機器執行引擎的統一外觀(Facade)。不同的虛擬機器實現,執行引擎可能會有解釋執行和編譯執行兩種,有可能兩
深入理解java虛擬機器—虛擬機器位元組碼執行引擎
引言 呼叫一個方法就會將該方法(將方法的各種資訊封裝成棧幀)進行壓棧,方法結束就會出棧。而棧幀是支援方法呼叫和執行的基礎結構,是虛擬機器棧的元素,棧幀儲存了一個方法的區域性變量表,運算元棧,動態連線和方法返回地址資訊等其他資訊。在編譯時就已經確定好了區域性變量
深入理解Java虛擬機器之虛擬機器位元組碼執行引擎
執行引擎是java虛擬機器最核心的組成部分之一。 物理機的執行引擎是建立在處理器、硬體、指令集和作業系統層面上的,而虛擬機器的執行引擎是由自己實現的,可以自行制定指令集與執行引擎的結構體系,並且能夠執行那些硬體不直接支援的指令集格式。 執行引擎在執行Java
深入理解Java虛擬機器 | 第六篇:虛擬機器位元組碼執行引擎
執行引擎是Java虛擬機器最核心的組成部分之一。“虛擬機器”是一個相對於“物理機”的概念,這兩種機器都有程式碼執行能力,其區別是物理機的執行引擎是直接建立在處理器、硬體、指令集和作業系統層面上的,而虛擬機器的執行引擎則是由自己實現的,因此可以自行制定指令集與執行引擎的結構體系
深入理解Java虛擬機器 位元組碼執行引擎
執行時棧幀結構 在JVM基本框架中已經提到過棧幀Frame結構。 區域性變量表 區域性變量表以Slot為基本單位,int,float,reference,boolean, byte都佔1 Slot;long和double資料被切割成連續2 Slot
《深入理解java虛擬機器》學習-第八章-虛擬機器位元組碼執行引擎-方法呼叫
1.概述 ① 方法呼叫並不等同於方法執行,方法呼叫階段唯一的任務就是確定被呼叫方法的版本(即呼叫哪一個方法),暫時還不涉及方法內部的具體執行過程。 ② 一切方法呼叫在Class檔案裡面儲存的都只是常量池中的符號引用,而不是方法在實際執行時記憶體佈局的入口地址(即直接引用);
深入理解虛擬機器之虛擬機器位元組碼執行引擎
《深入理解Java虛擬機器:JVM高階特性與最佳實踐(第二版》讀書筆記與常見相關面試題總結 1 概述 執行引擎是java虛擬機器最核心的組成部件之一。虛擬機器的執行引擎由自己實現,所以可以自行定製指令集與執行引擎的結構體系,並且能夠執行那些不被硬體直接支
《深入理解 Java 虛擬機器》讀書筆記:虛擬機器位元組碼執行引擎
# 正文 執行引擎是 Java 虛擬機器最核心的組成部分之一。在不同的虛擬機器實現裡,執行引擎在執行 Java 程式碼時可能會有解釋執行(通過直譯器執行)和編譯執行(通過即時編譯器產生原生代碼執行)兩種選擇,也可能兩者兼備。但從外觀上看,所有 Java 虛擬機器的執行引擎都是一致的:輸入的是位元組碼檔案,處
JVM十一:虛擬機器位元組碼執行引擎(2)
解析 繼續前面關於方法呼叫的話題,所有方法呼叫中的目標方法在 Class 檔案裡面都是一個常量池中的符號引用,在類載入的解析階段,會將其中的一部分符號引用轉化為直接引用,這種解析能成立的前提是:方法在程式真正執行之前就有一個可確定的呼叫版本,並且
JVM十一:虛擬機器位元組碼執行引擎(1)
執行引擎是Java最核心的組成部分之一。虛擬機器與物理機的區別:虛擬機器是一個相對“物理機”的概念,這兩種機器都有程式碼執行能力,其區別就是物理機的執行引擎是直接建立在處理器,硬體,指令集和作業系統層面