1. 程式人生 > >深入理解java虛擬機器—虛擬機器位元組碼執行引擎

深入理解java虛擬機器—虛擬機器位元組碼執行引擎

引言

呼叫一個方法就會將該方法(將方法的各種資訊封裝成棧幀)進行壓棧,方法結束就會出棧。而棧幀是支援方法呼叫和執行的基礎結構,是虛擬機器棧的元素,棧幀儲存了一個方法的區域性變量表,運算元棧,動態連線和方法返回地址資訊等其他資訊。在編譯時就已經確定好了區域性變量表的大小和運算元棧的大小。

區域性變量表

區域性變量表是用來存方法中的引數、變數,以slot為單位,this關鍵字是區域性變量表的第一個引數(索引為0),這是編譯時自動加上去的,this用於傳遞物件例項的引用。區域性變數中的slot是可以複用的,如果pc指標超出了slot的作用域,那麼這部分的slot則可以被其他變數使用。區域性變量表也會影響垃圾回收,當然GC Roots一部分的區域性變數仍然保持跟物件的關聯,那麼物件就不能被回收。

運算元棧

運算元棧也是一種先進後出的資料結構。運算元棧的最大深度在編譯時就已經確定了,在程式碼執行時運算元棧深度不會超過最大值。運算元棧就是用來存放運算元的,32位的資料佔運算元棧的容量為1,64位佔容量為2。例如a+b,那麼通過指令,會先將這兩個數壓棧,然後相加。在概念上運算元棧和區域性變量表是分開的,但在虛擬機器的實際實現中,有時會將兩個棧幀的運算元棧和區域性變量表共享記憶體。

動態連線

一部分方法的符號引用在執行期間轉化為直接引用,這一部分被稱為動態連線,棧幀中會儲存方法區中的所屬方法引用。

方法返回地址

一般方法返回地址儲存的是呼叫者呼叫該方法時的pc程式計數器值。如果正常退出,該值作為返回地址,如果因為異常退出,那麼返回地址根據異常處理器確定。方法的退出過程是將當前棧幀出棧,恢復上層方法的區域性變量表和運算元棧,如果有返回值就將返回值壓入呼叫者的棧中,調整pc計數器指向呼叫者方法後一條指令。

方法呼叫

方法的呼叫主要是確定被呼叫方法的版本。在類載入解析階段,有一部分方法呼叫的符號引用轉換成了直接引用,這些方法在程式開始之前就確定只有一個可呼叫的版本。這種方法呼叫叫做解析,主要包括靜態方法,私有方法,例項構造方法和父類方法,這兩種方法是不能被重寫的,所以在編譯時就被確定了,而且執行期不會被改變。這些方法都由invokestatic或invokespecial呼叫,都叫做非虛方法,除此之外還有一種是由final修飾的方法,雖然由invokevirtual呼叫,但是該方法無法被重寫,所以也是非虛方法。總之解析呼叫在類載入時,方法的版本就被確定了,符號引用轉換成了直接引用。
靜態分派:
上面說的是隻有一種方法版本,接下來說的是有多個方法版本,例如過載的方法,和重寫的方法,這時候就要進行方法分派。方法分派有靜態分派和動態分派。java是門面向物件的語言,多型是面向物件的其中一種特徵。多型跟方法分派是密不可分的,方法分派就是虛擬機器確定方法的呼叫版本,通俗就是確認呼叫哪個方法。靜態分派是在編譯期就確定了方法的呼叫版本,跟靜態分派有關的就是方法過載。變數有靜態型別,有實際型別。例如以下程式碼:Human是父類,Man是子類,那麼Human是man這個變數的靜態型別,Man是實際型別。

Human man = new Man();

如果一個相同的方法,引數型別不同就可以構成方法過載,那麼靜態分派是根據靜態型別來確認方法版本。例如下面這段虛擬碼:
類中有兩個方法,程式碼結果是呼叫第一個方法。

public void add(Human man){}
public void add(Man man){}
Human man = new Man();
方法呼叫:add(man);

動態分派:
動態分派跟方法重寫有關,動態分派的方法選擇是在執行時期確定,它會根據呼叫物件的實際型別去確認呼叫方法的版本。動態分派跟invokevirtual指令有關,該指令執行有以下步驟:
①找到棧頂第一個元素指向物件的實際型別,記作型別C;
②如果在型別C中找到與常量描述符和簡單名稱都相符的方法,並進行許可權校驗,如果通過則返回這個方法的直接引用,如果不通過則丟擲訪問非法異常。
③如果沒找到,則按照繼承關係從下往上依次對C的父類進行搜尋。
④如果沒找到,則丟擲java.lang.AbstractMethodError異常。

單分派和多分派

方法的接受者和方法的引數統稱為方法的宗量。單分派是基於一個宗量對方法進行選擇,多分派是基於多個宗量對方法進行選擇。java 是門靜態多分派,動態單分派的語言,靜態分派時根據方法的接收者和引數進行選擇,動態分派根據方法接收者進行選擇。

靜態型別語言和動態型別語言

java是一門靜態型別語言,靜態型別語言和動態型別語言的區別在於:動態型別語言的型別檢查是在執行期,而靜態型別語言的檢查是在編譯期,動態型別語言只有賦了值才有了型別。

基於棧的位元組碼解釋引擎

下面是大多數語言的編譯過程,從第一行到第三行的過程是一種完全編譯的編譯過程,就像c語言這種通過編譯最終形成可讓機器執行的可執行程式碼;從第一行到第二行這種,就像java這種語言,實現為一個半獨立的編譯器。java語言的編譯器將程式原始碼最終生成指令流,最後是由java虛擬機器進行執行。
這裡寫圖片描述
java的指令流是基於棧的指令集架構。還有一套常用的指令集架構就是基於暫存器的指令集。基於棧的指令集架構可移植性強;基於暫存器的架構跟處理器有關,可移植性不強,但是速度快。

相關推薦

深入理解Java虛擬機器(七)位元組執行引擎(棧幀、動態連線、方法呼叫)

執行引擎是Java虛擬機器最核心的組成部分之一。“虛擬機器”是一個相對於“物理機”的概念,這兩種機器都有程式碼執行能力,其區別是物理機的執行引擎是直接建立在處理器、硬體、指令集和作業系統層面上的,而虛擬機器的執行引擎則是由自己實現的,因此可以自行制定指令集與執行引擎的結構體系,並且能夠執

讀書筆記 ---- 《深入理解Java虛擬機器》---- 第7篇:虛擬機器位元組執行引擎

上一篇:虛擬機器類載入機制:https://blog.csdn.net/pcwl1206/article/details/84260914 第7篇:虛擬機器位元組碼執行引擎 執行引擎是Java虛擬機器最核心的組成部分之一。“虛擬機器”是一個相對於“物理機”的概念,這兩種機器都有程式碼執行能力

深入理解Java虛擬機器(類檔案結構+類載入機制+位元組執行引擎

周志明的《深入理解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虛擬機器----(七)位元組執行引擎

    位元組碼執行引擎是執行引擎是最重要的一部分,概念模型的總體外觀是一致的:輸入位元組碼,過程是位元組碼解析的等效過程,輸出結果。不同的虛擬機器有不同的具體實現,大體有解釋執行和編譯執行兩種選擇。 執行時棧幀結構:     棧楨在虛擬機器棧中,是支援方法呼叫和執行的結

[深入理解Java虛擬機器]第九章 位元組執行引擎-類載入及執行子系統的案例與實戰

概述 在Class檔案格式與執行引擎這部分中,使用者的程式能直接影響的內容並不太多, Class檔案以何種格式儲存,型別何時載入、如何連線,以及虛擬機器如何執行位元組碼指令等都是由虛擬機器直接控制的行為,使用者程式無法對其進行改變。能通過程式進行操作的,主要是

深入理解Java虛擬機器位元組執行引擎

本文首發於微信公眾號:BaronTalk 執行引擎是 Java 虛擬機器最核心的組成部分之一。「虛擬機器」是相對於「物理機」的概念,這兩種機器都有程式碼執行的能力,區別是物理機的執行引擎是直接建立在處理器、硬體、指令集和作業系統層面上的,而虛擬機器執行引擎是由自己實現的,因此可以自行制定指令集與執行

深入理解 Java 虛擬機器》讀書筆記:虛擬機器位元組執行引擎

# 正文 執行引擎是 Java 虛擬機器最核心的組成部分之一。在不同的虛擬機器實現裡,執行引擎在執行 Java 程式碼時可能會有解釋執行(通過直譯器執行)和編譯執行(通過即時編譯器產生原生代碼執行)兩種選擇,也可能兩者兼備。但從外觀上看,所有 Java 虛擬機器的執行引擎都是一致的:輸入的是位元組碼檔案,處

深入理解JVM虛擬機器讀書筆記【第八章】虛擬機器位元組執行引擎

8.1 概述 8.2 執行時棧幀結構 8.2.1 區域性變量表 8.2.2 運算元棧 8.2.3 動態連線 8.2.4 方法返回地址

深入理解JVM虛擬機器(七):虛擬機器位元組執行引擎

程式碼編譯的結果就是從本地機器碼轉變為位元組碼。我們都知道,編譯器將Java原始碼轉換成位元組碼?那麼位元組碼是如何被執行的呢?這就涉及到了JVM位元組碼執行引擎,執行引擎負責具體的程式碼呼叫及執行過程。就目前而言,所有的執行引擎的基本一致: 輸入:位元組碼檔案

深入Java虛擬機器】之七:深入JVM位元組執行引擎

我們都知道,在當前的Java中(1.0)之後,編譯器講原始碼轉成位元組碼,那麼位元組碼如何被執行的呢?這就涉及到了JVM的位元組碼執行引擎,執行引擎負責具體的程式碼呼叫及執行過程。就目前而言,所有的執行引擎的基本一致: 輸入:位元組碼檔案 處理:位元組碼解析 輸出:執

深入理解JVM總結——虛擬機器位元組執行引擎

執行引擎是Java虛擬機器最核心的組成部分之一。物理機和虛擬機器都有執行程式碼的能力。區別在於物理機的執行引擎是直接建立在處理器、硬體、指令集和作業系統層面上的,而虛擬機器的執行引擎則是由自己實現的,因此可以自行指定指令集與執行引擎的結構體系,並且能夠執行那些不

深入理解虛擬機器虛擬機器位元組執行引擎

《深入理解Java虛擬機器:JVM高階特性與最佳實踐(第二版》讀書筆記與常見相關面試題總結 1 概述 執行引擎是java虛擬機器最核心的組成部件之一。虛擬機器的執行引擎由自己實現,所以可以自行定製指令集與執行引擎的結構體系,並且能夠執行那些不被硬體直接支

深入理解jvm(四):虛擬機器位元組執行引擎

執行時棧幀 每一個方法從呼叫開始到執行完成都對應著一張棧幀的進棧和出棧。棧幀中儲存著區域性變量表,運算元表,動態連結和方法返回地址。位於虛擬機器最頂層的稱為當前方法棧。 區域性變量表 儲存當前方法的區域性變數和引數,區域性變量表的容量以變數槽slo

jdk原始碼解析(八)——Java虛擬機器位元組執行引擎

在前面我們瞭解了jvm執行時資料區,那個jvm圖中有執行引擎,那麼今天就解釋一下Java虛擬機器位元組碼執行引擎。 1 定義 Java虛擬機器位元組碼執行引擎是jvm最核心的組成部分之一,“虛擬機器” 是一個相對於 “物理機” 的概念,這兩種機器都有程式碼執行能力,其區別是物理機的執行