最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談JVM系列之JIT中的Virtual Call

 更新時間:2021年06月03日 08:53:21   作者:flydean  
什么是Virtual Call?Virtual Call在java中的實現(xiàn)是怎么樣的?Virtual Call在JIT中有沒有優(yōu)化?所有的答案看完這篇文章就明白了。

Virtual Call和它的本質(zhì)

有用過PrintAssembly的朋友,可能會在反編譯的匯編代碼中發(fā)現(xiàn)有些方法調(diào)用的說明是invokevirtual,實際上這個invokevirtual就是Virtual Call。

Virtual Call是什么呢?

面向?qū)ο蟮木幊陶Z言基本上都支持方法的重寫,我們考慮下面的情況:

private static class CustObj
{
    public void methodCall()
    {
        if(System.currentTimeMillis()== 0){
            System.out.println("CustObj is very good!");
        }
    }
}
private static class CustObj2 extends  CustObj
{
    public final void methodCall()
    {
        if(System.currentTimeMillis()== 0){
            System.out.println("CustObj2 is very good!");
        }
    }
}

我們定義了兩個類,CustObj是父類CustObj2是子類。然后我們通一個方法來調(diào)用他們:

public static void doWithVMethod(CustObj obj)
{
    obj.methodCall();
}

因為doWithVMethod的參數(shù)類型是CustObj,但是我們同樣也可以傳一個CustObj2對象給doWithVMethod。

怎么傳遞這個參數(shù)是在運行時決定的,我們很難在編譯的時候判斷到底該如何執(zhí)行。

那么JVM會怎么處理這個問題呢?

答案就是引入VMT(Virtual Method Table),這個VMT存儲的是該class對象中所有的Virtual Method。

然后class的實例對象保存著一個VMT的指針,執(zhí)行VMT。

程序運行的時候首先加載實例對象,然后通過實例對象找到VMT,通過VMT再找到對應(yīng)的方法地址。

Virtual Call和classic call

Virtual Call意思是調(diào)用方法的時候需要依賴不同的實例對象。而classic call就是直接指向方法的地址,而不需要通過VMT表的轉(zhuǎn)換。

所以classic call通常會比Virtual Call要快。

那么在java中是什么情況呢?

在java中除了static, private和構(gòu)造函數(shù)之外,其他的默認(rèn)都是Virtual Call。

Virtual Call優(yōu)化單實現(xiàn)方法的例子

有些朋友可能會有疑問了,java中其他方法默認(rèn)都是Virtual Call,那么如果只有一個方法的實現(xiàn),性能不會受影響嗎?

不用怕,JIT足夠智能,可以檢測到這種情況,在這種情況下JIT會對Virtual Call進(jìn)行優(yōu)化。

接下來,我們使用JIT Watcher來進(jìn)行Assembly代碼的分析。

要運行的代碼如下:

public class TestVirtualCall {

    public static void main(String[] args) throws InterruptedException {
        CustObj obj = new CustObj();
        for (int i = 0; i < 10000; i++)
        {
            doWithVMethod(obj);
        }
        Thread.sleep(1000);
    }

    public static void doWithVMethod(CustObj obj)
    {
        obj.methodCall();
    }

    private static class CustObj
    {
        public void methodCall()
        {
            if(System.currentTimeMillis()== 0){
                System.out.println("CustObj is very good!");
            }
        }
    }
}

上面的例子中我們只定義了一個類的方法實現(xiàn)。

在JIT Watcher的配置中,我們禁用inline,以免inline的結(jié)果對我們的分析進(jìn)行干擾。

如果你不想使用JIT Watcher,那么可以在運行是添加參數(shù)-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:-Inline, 這里使用JIT Watcher是為了方便分析。

好了運行代碼:

運行完畢,界面直接定位到我們的JIT編譯代碼的部分,如下圖所示:

obj.methodCall相對應(yīng)的byteCode中,大家可以看到第二行就是invokevirtual,和它對應(yīng)的匯編代碼我也在最右邊標(biāo)明了。

大家可以看到在invokevirtual methodCall的最下面,已經(jīng)寫明了optimized virtual_call,表示這個方法已經(jīng)被JIT優(yōu)化過了。

接下來,我們開啟inline選項,再運行一次:

大家可以看到methodCall中的System.currentTimeMillis已經(jīng)被內(nèi)聯(lián)到methodCall中了。

因為內(nèi)聯(lián)只會發(fā)生在classic calls中,所以也側(cè)面說明了methodCall方法已經(jīng)被優(yōu)化了。

Virtual Call優(yōu)化多實現(xiàn)方法的例子

上面我們講了一個方法的實現(xiàn),現(xiàn)在我們測試一下兩個方法的實現(xiàn):

public class TestVirtualCall2 {

    public static void main(String[] args) throws InterruptedException {
        CustObj obj = new CustObj();
        CustObj2 obj2 = new CustObj2();
        for (int i = 0; i < 10000; i++)
        {
            doWithVMethod(obj);
            doWithVMethod(obj2);

        }
        Thread.sleep(1000);
    }

    public static void doWithVMethod(CustObj obj)
    {
        obj.methodCall();
    }

    private static class CustObj
    {
        public void methodCall()
        {
            if(System.currentTimeMillis()== 0){
                System.out.println("CustObj is very good!");
            }
        }
    }
    private static class CustObj2 extends  CustObj
    {
        public final void methodCall()
        {
            if(System.currentTimeMillis()== 0){
                System.out.println("CustObj2 is very good!");
            }
        }
    }
}

上面的例子中我們定義了兩個類CustObj和CustObj2。

再次運行看下結(jié)果,同樣的,我們還是禁用inline。

大家可以看到結(jié)果中,首先對兩個對象做了cmp,然后出現(xiàn)了兩個優(yōu)化過的virtual call。

這里比較的作用就是找到兩個實例對象中的方法地址,從而進(jìn)行優(yōu)化。

那么問題來了,兩個對象可以優(yōu)化,三個對象,四個對象呢?

我們選擇三個對象來進(jìn)行分析:

public class TestVirtualCall4 {

    public static void main(String[] args) throws InterruptedException {
        CustObj obj = new CustObj();
        CustObj2 obj2 = new CustObj2();
        CustObj3 obj3 = new CustObj3();
        for (int i = 0; i < 10000; i++)
        {
            doWithVMethod(obj);
            doWithVMethod(obj2);
            doWithVMethod(obj3);

        }
        Thread.sleep(1000);
    }

    public static void doWithVMethod(CustObj obj)
    {
        obj.methodCall();
    }

    private static class CustObj
    {
        public void methodCall()
        {
            if(System.currentTimeMillis()== 0){
                System.out.println("CustObj is very good!");
            }
        }
    }
    private static class CustObj2 extends  CustObj
    {
        public final void methodCall()
        {
            if(System.currentTimeMillis()== 0){
                System.out.println("CustObj2 is very good!");
            }
        }
    }
    private static class CustObj3 extends  CustObj
    {
        public final void methodCall()
        {
            if(System.currentTimeMillis()== 0){
                System.out.println("CustObj3 is very good!");
            }
        }
    }
}

運行代碼,結(jié)果如下:

總結(jié)

本文介紹了Virtual Call和它在java代碼中的使用,并在匯編語言的角度對其進(jìn)行了一定程度的分析。

以上就是淺談JVM系列之JIT中的Virtual Call的詳細(xì)內(nèi)容,更多關(guān)于JVM系列之JIT中的Virtual Call的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Spring三級緩存解決循環(huán)依賴

    Spring三級緩存解決循環(huán)依賴

    本文主要介紹了Spring三級緩存解決循環(huán)依賴,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • Java日常練習(xí)題,每天進(jìn)步一點點(51)

    Java日常練習(xí)題,每天進(jìn)步一點點(51)

    下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望可以幫到你
    2021-08-08
  • SpringBoot3實戰(zhàn)教程之實現(xiàn)接口簽名驗證功能

    SpringBoot3實戰(zhàn)教程之實現(xiàn)接口簽名驗證功能

    接口簽名是一種重要的安全機(jī)制,用于確保 API 請求的真實性、數(shù)據(jù)的完整性以及防止重放攻擊,這篇文章主要介紹了SpringBoot3實戰(zhàn)教程之實現(xiàn)接口簽名驗證功能,需要的朋友可以參考下
    2025-04-04
  • Java中InetAddress類的使用

    Java中InetAddress類的使用

    InetAddress類是Java中用于表示IP地址的類,本文就來介紹一下Java中InetAddress類的使用,具有一定的參考價值,感興趣的可以了解一下
    2023-09-09
  • Java后端配置允許跨域方式

    Java后端配置允許跨域方式

    本文介紹了在不同技術(shù)和框架中配置跨域資源共享(CORS)的方法,包括使用SpringMVC的@CrossOrigin注解、SpringBoot的全局CORS配置、SpringSecurity中的CORS集成以及手動設(shè)置響應(yīng)頭,根據(jù)具體需求和技術(shù)棧,選擇合適的方法來確保跨域請求的安全性和有效性
    2025-02-02
  • 總結(jié)Java常用加解密方法AES?SHA1?md5

    總結(jié)Java常用加解密方法AES?SHA1?md5

    這篇文章主要為大家介紹了Java常用加密方法AES?SHA1?md5總結(jié)及示例demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • Java中的幾種關(guān)鍵字的使用小結(jié)

    Java中的幾種關(guān)鍵字的使用小結(jié)

    本文主要介紹了Java中的幾種關(guān)鍵字的使用小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 自定義類加載器的父類為何是AppClassLoader說明

    自定義類加載器的父類為何是AppClassLoader說明

    這篇文章主要介紹了自定義類加載器的父類為何是AppClassLoader說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • Java使用poi生成word文檔的簡單實例

    Java使用poi生成word文檔的簡單實例

    Java POI是一個用于處理Microsoft Office文件(如Word、Excel和PowerPoint)的API,它是一個開源庫,允許Java開發(fā)者讀取、創(chuàng)建和修改這些文檔,本文給大集介紹了Java使用poi生成word文檔的簡單實例,感興趣的朋友可以參考下
    2024-06-06
  • SpringBoot與Quartz集成實現(xiàn)分布式定時任務(wù)集群的代碼實例

    SpringBoot與Quartz集成實現(xiàn)分布式定時任務(wù)集群的代碼實例

    今天小編就為大家分享一篇關(guān)于SpringBoot與Quartz集成實現(xiàn)分布式定時任務(wù)集群的代碼實例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03

最新評論

横山县| 仙居县| 白山市| 来凤县| 大同县| 遂溪县| 浦北县| 郑州市| 临泽县| 阿鲁科尔沁旗| 黄大仙区| 华蓥市| 青河县| 宁德市| 监利县| 丹江口市| 晋州市| 上犹县| 黄龙县| 武宁县| 托克托县| 和林格尔县| 遂平县| 丰县| 咸宁市| 渝中区| 九龙坡区| 金溪县| 黎城县| 抚州市| 建始县| 蒲江县| 星座| 诏安县| 即墨市| 左贡县| 温泉县| 太和县| 安化县| 望谟县| 桦甸市|