Java字節(jié)碼文件(一)

字節(jié)碼其實是一個二進制流文件,按照JVM規(guī)范排列的0101數(shù)字,我們也可以使用010 Editor編輯器打開查看:


image.png

這里使用十六進制表示,那么這又是什么意思呢?
根據(jù)Oracle官方文檔說明,一個字節(jié)碼文件應(yīng)包含以下信息:

ClassFile {
    u4             magic;                    // 魔數(shù),4字節(jié),必須以CA FE BA BE 開頭
    u2             minor_version;      // javac的次版本號,2字節(jié)
    u2             major_version;      // javac的主版本號,2字節(jié)
    u2             constant_pool_count;  //常量池數(shù)量,2字節(jié)
    cp_info        constant_pool[constant_pool_count-1];  //常量池數(shù)組,長度不定
    u2             access_flags;  //訪問標(biāo)識符,2字節(jié)
    u2             this_class;   // 當(dāng)前類索引,2字節(jié)
    u2             super_class; // 父類索引,2字節(jié)
    u2             interfaces_count; // 接口索引,2字節(jié)
    u2             interfaces[interfaces_count]; // 接口數(shù)組
    u2             fields_count;  // 字段表數(shù)量
    field_info     fields[fields_count]; // 字段數(shù)組
    u2             methods_count; //方法數(shù)
    method_info    methods[methods_count]; //方法數(shù)組
    u2             attributes_count; //屬性表數(shù)量
    attribute_info attributes[attributes_count];
}
  • 常量池數(shù)據(jù)區(qū):數(shù)據(jù)區(qū)是由(constant_pool_count-1)個cp_info結(jié)構(gòu)組成,一個cp_info結(jié)構(gòu)對應(yīng)一個常量。在字節(jié)碼中共有14種類型的cp_info,每種類型的結(jié)構(gòu)都是固定的。
    image.png
  • 訪問標(biāo)識,JVM規(guī)范規(guī)定了如下圖的訪問標(biāo)志(Access_Flag)


    image.png

    image.png

    需要注意的是,JVM并沒有窮舉所有的訪問標(biāo)志,而是使用按位或操作來進行描述的,比如某個類的修飾符為public final,則對應(yīng)的訪問修飾符的值為ACC_PUBLIC | ACC_FINAL,即0x0001 | 0x0010=0x0011

  • 當(dāng)前類索引,父類索引,接口索引可以根據(jù)索引值去常量池查找


    image.png
  • 字段表方法表參考:字節(jié)碼增強技術(shù)探索 - 美團技術(shù)團隊 (meituan.com)

也可以在AS中安裝jclasslib插件,點擊view->show ByteCode With jclasslib查看:


image.png

也可以使用命令行查看:

D:\desktop> javac StringOperation.java
D:\desktop> javap -v StringOperation.class

不過上面的發(fā)匯編結(jié)果,main 函數(shù)無法看到LocalVariableTable

 public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=6, args_size=1
         0: ldc           #7                  // String a
         2: astore_1
         3: ldc           #7                  // String a
         5: astore_2
         9: dup
        10: ldc           #7                  // String a
        12: invokespecial #11                 // Method java/lang/String."<init>":(Ljava/lang/String;)V
        18: astore        4
        20: aload_2
        21: invokedynamic #16,  0             // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
        26: astore        5
        28: return
      LineNumberTable:
        line 3: 0
        line 4: 3
        line 5: 6
        line 6: 16
        line 7: 20
        line 8: 28
   // 這里沒有LocalVariableTable
}
SourceFile: "StringOperation.java"

修改下編譯選項,就可以看到了

D:\desktop> javac -g StringOperation.java
D:\desktop> javap -v StringOperation.class
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容