91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

? JVM中執行引擎的案例分析

發布時間:2020-11-09 14:37:32 來源:億速云 閱讀:166 作者:小新 欄目:編程語言

小編給大家分享一下 JVM中執行引擎的案例分析,希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去探討吧!

 JVM中的執行引擎在執行java代碼的時候,一般有解釋執行(通過解釋器執行)和編譯執行(通過即時編譯器產生本地代碼執行)兩種選擇。

棧幀

定義:

棧幀是用于支持虛擬機進行方法調用和方法執行的數據結構,它位于虛擬機棧里面。

作用:

每個方法從調用開始到執行完成的過程中,都對應著一個棧幀在虛擬機棧里面從入棧到出棧的過程。

? JVM中執行引擎的案例分析

特點:

(1)棧幀包括了局部變量表,操作數棧等,到底是需要多大的局部變量表,多深的操作數棧是在編譯期確定的。因為一個棧幀需要分配多少內存,不會受到程序運行期變量數據的影響。

(2)兩個棧幀之間的數據共享。在概念模型中,兩個棧幀是完全獨立的,但是在虛擬機的實現里會做一些優化處理,令兩個棧幀出現一部分重疊。這樣在進行方法調用時,就可以共用一部分數據,無須進行額外的參數復制傳遞。

? JVM中執行引擎的案例分析

(1)局部變量表

局部變量表是一組變量值存儲空間,用于存放方法參數和方法內部定義的局部變量。

//方法參數   
max(int a,int b)
int a;//全局變量
void say(){
   int b=0;//局部變量
 }

局部變量和類變量(用static修飾的變量)不同

類變量有兩次賦初始值的過程:準備階段(賦予系統初始值)和初始化階段(賦予程序員定義的初始值)。所以即使在初始化階段沒有為類變量賦值也沒關系,它仍然有一個確定的初始值。
但局部變量不一樣,如果定義了,但沒有賦初始值,是不能使用的。

(2)操作棧

當一個方法剛剛開始執行的時候,這個方法的操作數棧是空的,在方法的執行過程中,會有各種字節碼指令往操作數棧中寫入和提取內容,也就是出棧、入棧操作。

例如,計算:

int a=2+3

操作數棧中最接近棧頂的兩個元素是2和3,當執行iadd指令時,會將2和3出棧并相加,然后將相加的結果5入棧。

(3)動態鏈接

Class文件的常量池中存有大量的符號引用,字節碼中的方法調用指令就以常量池中指向方法的符號引用作為參數。這些符號引用分為兩部分:

靜態解析:在類加載階段或第一次使用的時候就轉化為直接引用。動態鏈接:在每一次運行期間轉化為直接引用。

(4)返回地址

當一個方法開始執行后,只有兩種方式可以退出這個方法:正常退出、異常退出。無論采用何種退出方式,在方法退出之后,都需要返回到方法被調用的位置,程序才能繼續執行。

當方法正常退出時

調用者的PC計數器作為返回地址。棧幀中一般會保存這個計數器值。

當方法異常退出時

返回地址是要通過異常處理器表來確定的。棧幀中一般不會保存這部分信息。

方法調用

方法調用是確定調用哪一個方法。

(1)解析

對“編譯器可知,運行期不可變”的方法進行調用稱為解析。符合這種要求的方法主要包括

靜態方法,用static修飾的方法私有方法,用private修飾的方法

(2)分派

分派講解了虛擬機如何確定正確的目標方法。分派分為靜態分派和動態分派。講解靜動態分派之前,我們先看個多態的例子。

Human man=new Man();

在這段代碼中,Human為靜態類型,其在編譯期是可知的。Man是實際類型,結果在運行期才可確定,編譯期在編譯程序的時候并不知道一個對象的實際類型是什么。

靜態分派:

所有依賴靜態類型來定位方法執行版本的分派動作稱為靜態分派。它的典型應用是重載。

public class StaticDispatch{  
   static abstract class Human{  
    }  
   static class Man extends Human{
    }
    static class Woman extends Human{
    }
    public void say(Human hum){  
        System.out.println("I am human");  
    }  
    public void say(Man hum){  
        System.out.println("I am man");  
    }  
    public void say(Woman hum){  
        System.out.println("I am woman");  
    }  
    
    public static void main(String[] args){  
        Human man = new Man();  
        Human woman = new Woman();  
        StaticDispatch sr = new StaticDispatch();  
        sr.say(man);  
        sr.say(woman);  
    }  
}

運行結果是:

I am human
I am human

為什么會產生這個結果呢?
因為編譯器在重載時,是通過參數的靜態類型而不是實際類型作為判斷依據的。在編譯階段,javac編譯器會根據參數的靜態類型決定使用哪個重載版本,所以兩個對say()方法的調用實際為sr.say(Human)。

動態分派:

在運行期根據實際類型確定方法執行版本的分派過程。它的典型應用是重寫。

public class DynamicDispatch{  
   static abstract class Human{  
            protected abstract void say();
    }  
   static class Man extends Human{
            @Override
             protected abstract void say(){
             System.out.println("I am man");  
            }
    }
    static class Woman extends Human{
         @Override
             protected abstract void say(){
             System.out.println("I am woman ");  
            }
    }
    
    public static void main(String[] args){  
        Human man = new Man();  
        Human woman = new Woman();  
        man.say();
        woman.say();
        man=new Woman();
        man.say();
    }  
}

運行結果:

I am man
I am woman 
I am woman

這似乎才是我們平時敲的java代碼。對于方法重寫,在運行時才確定調用哪個方法。由于Human的實際類型是man,因此調用的是man的name方法。其余的同理。

動態分派的實現依賴于方法區中的虛方法表,它里面存放著各個方法的實際入口地址。如果某個方法在子類中被重寫了,那子類方法表中的地址將會替換為指向子類實現版本的入口地址,否則,指向父類的實現入口。

單分派和多分派:

方法的接收者與方法的參數統稱為方法的宗量,根據分派基于多少種宗量,分為單分派和多分派。

在靜態分派中,需要調用者的實際類型和方法參數的類型才能確定方法版本,所以其是多分派類型。在動態分派中,已經知道了參數的實際類型,所以此時只需知道方法調用者的實際類型就可以確定出方法版本,所以其是單分派類型。綜上,java是一門靜態多分派,動態單分派的語言。

字節碼解釋執行引擎

虛擬機中的字節碼解釋執行引擎是基于棧的。下面通過一段代碼來仔細看一下其解釋的執行過程。

public int calc(){  
    int a = 100;  
    int b = 200;  
    int c = 300;  
    return (a + b) * c;  
}

第一步:將100入棧。

? JVM中執行引擎的案例分析

第二步:將操作棧中的100出棧并存放到局部變量中。后面的200,300同理。

? JVM中執行引擎的案例分析

第三步:將局部變量表中的100復制到操作數棧頂。

? JVM中執行引擎的案例分析

第四步:將局部變量表中的200復制到操作數棧頂。

? JVM中執行引擎的案例分析

第五步:將100和200出棧,做整型加法,最后將結果300重新入棧。

? JVM中執行引擎的案例分析

第六步:將第三個數300從局部變量表復制到棧頂。接下來就是將兩個300出棧,進行整型乘法,將最后的結果90000入棧。

? JVM中執行引擎的案例分析

第七步:方法結束,將操作數棧頂的整型值返回給此方法的調用者。

? JVM中執行引擎的案例分析

看完了這篇文章,相信你對 JVM中執行引擎的案例分析有了一定的了解,想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

jvm
AI

长阳| 称多县| 柘荣县| 高阳县| 云梦县| 洛南县| 长海县| 阳泉市| 板桥市| 达拉特旗| 乌拉特前旗| 莎车县| 苗栗县| 临桂县| 伊川县| 鸡西市| 容城县| 张家界市| 遵化市| 京山县| 罗甸县| 四平市| 上林县| 武乡县| 兰西县| 嘉荫县| 南通市| 长乐市| 星子县| 大同县| 固安县| 九龙县| 江口县| 射洪县| 宁津县| 海阳市| 崇仁县| 平遥县| 宜昌市| 漠河县| 都江堰市|