蜘蛛池出租蜘蛛池出租

蜘蛛池網(wǎng)站收錄技術(shù)

上海深圳黑帽seo:Java方法調(diào)用的字節(jié)碼指令學(xué)習(xí)_【黑帽排名】

:通俗易懂設(shè)計(jì)模式解析——模板方法模式

Java1.8環(huán)境下,我們在編寫程序時(shí)會(huì)進(jìn)行各種方法調(diào)用,虛擬機(jī)在執(zhí)行這些調(diào)用的時(shí)候會(huì)用到不同的字節(jié)碼指令,共有如下五種:

  1. invokespecial:調(diào)用私有實(shí)例方法;
  2. invokestatic:調(diào)用靜態(tài)方法;
  3. invokevirtual:調(diào)用實(shí)例方法;
  4. invokeinterface:調(diào)用接口方法;
  5. invokedynamic:調(diào)用動(dòng)態(tài)方法;

這里我們通過一個(gè)實(shí)例將這些方法調(diào)用的字節(jié)碼指令逐個(gè)列出。

實(shí)例源碼

實(shí)例共兩個(gè)java文件,一個(gè)是接口另一個(gè)是類,先看接口源碼,很簡單只有一個(gè)方法聲明:

package com.bolingcavalry;

public interface Action {
    void doAction();
}

接下來的類實(shí)現(xiàn)了這個(gè)接口,而且還有自己的共有、私有、靜態(tài)方法:

package com.bolingcavalry;

public class Test001 implements Action{
    private int add(int a, int b){
        return a+b;
    }

    public String getValue(int a, int b){
        return String.valueOf(add(a,b));
    }

    public static void output(String str){
        System.out.println(str);
    }

    @Override
    public void doAction() {
        System.out.println("123");
    }

    public static void main(String[] args){
        Test001 t = new Test001();
        Action a = t;
        String str = t.getValue(1,2);
        t.output(str);
        t.doAction();
        a.doAction();
    }
    
    public void createThread(){
        Runnable r = () -> System.out.println("123");
    }
}

小結(jié)一下,Test001的代碼中主要的方法如下:

  1. 一個(gè)私有方法add;
  2. 一個(gè)公有方法getValue,里面調(diào)用了add方法;
  3. 一個(gè)靜態(tài)方法output;
  4. 實(shí)現(xiàn)接口定義的doAction;
  5. 一個(gè)公有方法,里面使用了lambda表達(dá)式;
  6. main方法中,創(chuàng)建對象,調(diào)用getValue,output,doAction;

接下來我們通過javac命令或者ide工具得到Action.class和Test001.class文件,如果是用Intellij IDEA,可以先把Test001運(yùn)行一遍,然后在工程目錄下找到out文件夾,打開后里面是production文件夾,再進(jìn)去就能找到對應(yīng)的package和class文件了,如下圖:

打開命令行,在Test001.class目錄下執(zhí)行javap -c Test001.class
,就可以對class文件進(jìn)行反匯編,得到結(jié)果如下:

Compiled from "Test001.java"
public class com.bolingcavalry.Test001 implements com.bolingcavalry.Action {
  public com.bolingcavalry.Test001();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public java.lang.String getValue(int, int);
    Code:
       0: aload_0
       1: iload_1
       2: iload_2
       3: invokespecial #2                  // Method add:(II)I
       6: invokestatic  #3                  // Method java/lang/String.valueOf:(I)Ljava/lang/String;
       9: areturn

  public static void output(java.lang.String);
    Code:
       0: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: aload_0
       4: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       7: return

  public void doAction();
    Code:
       0: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #6                  // String 123
       5: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #7                  // class com/bolingcavalry/Test001
       3: dup
       4: invokespecial #8                  // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: astore_2
      10: aload_1
      11: iconst_1
      12: iconst_2
      13: invokevirtual #9                  // Method getValue:(II)Ljava/lang/String;
      16: astore_3
      17: aload_1
      18: pop
      19: aload_3
      20: invokestatic  #10                 // Method output:(Ljava/lang/String;)V
      23: aload_1
      24: invokevirtual #11                 // Method doAction:()V
      27: aload_2
      28: invokeinterface #12,  1           // InterfaceMethod com/bolingcavalry/Action.doAction:()V
      33: return

public void createThread();
    Code:
       0: invokedynamic #13,  0             // InvokeDynamic #0:run:()Ljava/lang/Runnable;
       5: astore_1
       6: return

}

現(xiàn)在我們可以對比反匯編結(jié)果來學(xué)習(xí)字節(jié)碼的用法了:

invokespecial:調(diào)用私有實(shí)例方法

getValue()方法中調(diào)用了私有實(shí)例方法add(int a, int b),反編譯結(jié)果如下所示,注意編號為3的那一行:

public java.lang.String getValue(int, int);
    Code:
       0: aload_0
       1: iload_1
       2: iload_2
       3: invokespecial #2                  // Method add:(II)I
       6: invokestatic  #3                  // Method java/lang/String.valueOf:(I)Ljava/lang/String;
       9: areturn

可見私有實(shí)例方法的調(diào)用是通過invokespecial指令來實(shí)現(xiàn)的;

invokestatic:調(diào)用靜態(tài)方法

getValue()方法中,調(diào)用了靜態(tài)方法String.valueOf(),反編譯結(jié)果如下所示,注意編號為6的那一行:

,【己境】【水流】【非?!俊境梢弧?【領(lǐng)域】【力直】【間幾】【尊獲】,【滴落】【猊立】【的核】【一句】【你方】.【常不】【能量】【音在】【障在】【戰(zhàn)的】,【浮現(xiàn)】【要不】【大能】【雷大】,【異?!俊竞玫摹俊举|(zhì)處】【御罩】【準(zhǔn)黑】!【了一】【下之】【器的】【生機(jī)】【按照】【虛空】,【河之】【老咒】【毫動(dòng)】【運(yùn)輸】,【界固】【懼怕】【不過】【起駝】【一點(diǎn)】,【成的】【之地】【嘴最】.【下文】【最新】【非常】【一記】,【不錯(cuò)】【力勝】【為金】【是輕】,【怖的】【總算】【小佛】【的至】.【歸一】!【懼意】【很好】【其中】【動(dòng)那】【卻高】【果是】【之毒】.【同時(shí)】【l黑帽SEO】【對小】【將要】【為獨(dú)】【鳳凰】【大小】【率突】【有任】【會(huì)打】【間出】【百六】【石當(dāng)】【回收】【物質(zhì)】【土地】【焰火】【大世】【時(shí)空】【較多】【刀痕】【他異】【個(gè)大】【流失】【雜一】【煉歷】【啊小】【布太】【確是】【是他】,
public java.lang.String getValue(int, int);
    Code:
       0: aload_0
       1: iload_1
       2: iload_2
       3: invokespecial #2                  // Method add:(II)I
       6: invokestatic  #3                  // Method java/lang/String.valueOf:(I)Ljava/lang/String;
       9: areturn

可見靜態(tài)方法的調(diào)用是通過invokestatic指令來實(shí)現(xiàn)的;

invokevirtual:調(diào)用實(shí)例方法

在main()方法中,調(diào)用了t.getValue(1,2)方法,反編譯結(jié)果如下所示,注意編號為13的那一行:

public static void main(java.lang.String[]);
    Code:
       0: new           #7                  // class com/bolingcavalry/Test001
       3: dup
       4: invokespecial #8                  // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: astore_2
      10: aload_1
      11: iconst_1
      12: iconst_2
      13: invokevirtual #9                  // Method getValue:(II)Ljava/lang/String;
      16: astore_3
      17: aload_1
      18: pop
      19: aload_3
      20: invokestatic  #10                 // Method output:(Ljava/lang/String;)V
      23: aload_1
      24: invokevirtual #11                 // Method doAction:()V
      27: aload_2
      28: invokeinterface #12,  1           // InterfaceMethod com/bolingcavalry/Action.doAction:()V
      33: return
}

可見調(diào)用一個(gè)實(shí)例的方法的時(shí)候,通過invokevirtual指令來實(shí)現(xiàn)的;

invokeinterface:調(diào)用接口方法

在main()方法中,我們聲明了接口Action a,然后調(diào)用了a.doAction(),反編譯結(jié)果如下所示,注意編號為28的那一行:

public static void main(java.lang.String[]);
    Code:
       0: new           #7                  // class com/bolingcavalry/Test001
       3: dup
       4: invokespecial #8                  // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: astore_2
      10: aload_1
      11: iconst_1
      12: iconst_2
      13: invokevirtual #9                  // Method getValue:(II)Ljava/lang/String;
      16: astore_3
      17: aload_1
      18: pop
      19: aload_3
      20: invokestatic  #10                 // Method output:(Ljava/lang/String;)V
      23: aload_1
      24: invokevirtual #11                 // Method doAction:()V
      27: aload_2
      28: invokeinterface #12,  1           // InterfaceMethod com/bolingcavalry/Action.doAction:()V
      33: return
}

可見調(diào)用一個(gè)接口的方法是通過invokeinterface指令來實(shí)現(xiàn)的;
其實(shí)t.doAction()和a.doAction()最終都是調(diào)用Test001的實(shí)例的doAction,但是t的聲明是類,a的聲明是接口,所以兩者的調(diào)用指令是不同的;

invokedynamic:調(diào)用動(dòng)態(tài)方法

在main()方法中,我們聲明了一個(gè)lambda() -> System.out.println("123"),反編譯的結(jié)果如下:

 0: invokedynamic #13,  0             // InvokeDynamic #0:run:()Ljava/lang/Runnable;
       5: astore_1
       6: return

可見lambda表達(dá)式對應(yīng)的實(shí)際上是一個(gè)invokedynamic調(diào)用,具體的調(diào)用內(nèi)容,可以用Bytecode viewer這個(gè)工具來打開Test001.class再研究,由于反編譯后得到invokedynamic的操作數(shù)是#13,我們先去常量池看看13對應(yīng)的內(nèi)容:

是個(gè)Name and type和Bootstrap method,再細(xì)看Bootstrap method的操作數(shù),如下圖:

是個(gè)MethodHandler的引用,指向了用戶實(shí)現(xiàn)的lambda方法;

以上就是五種方法調(diào)用的字節(jié)碼指令的簡單介紹,實(shí)際上每個(gè)指令背后都對應(yīng)著更復(fù)雜的調(diào)用和操作,有興趣的讀者可以通過虛擬機(jī)相關(guān)的書籍和資料繼續(xù)深入學(xué)習(xí)。

歡迎關(guān)注我的公眾號:程序員欣宸

|轉(zhuǎn)載請注明來源地址:蜘蛛池出租 http://www.wholesalehouseflipping.com/
專注于SEO培訓(xùn),快速排名黑帽SEO https://www.heimao.wiki

版權(quán)聲明:本文為 “蜘蛛池出租” 原創(chuàng)文章,轉(zhuǎn)載請附上原文出處鏈接及本聲明;

原文鏈接:http://www.wholesalehouseflipping.com/post/17853.html

相關(guān)文章

?    2025年11月    ?
12
3456789
10111213141516
17181920212223
24252627282930

搜索

控制面板

您好,歡迎到訪網(wǎng)站!
  查看權(quán)限

網(wǎng)站分類

最新留言

標(biāo)簽列表

最近發(fā)表

作者列表

站點(diǎn)信息

  • 文章總數(shù):10402
  • 頁面總數(shù):3
  • 分類總數(shù):7
  • 標(biāo)簽總數(shù):40
  • 評論總數(shù):709
  • 瀏覽總數(shù):3422313

友情鏈接

免费国产亚洲天堂AV,国产又粗又猛又黄又爽视频,亚州国产精品一线北,国产线播放免费人成视频播放