Class文件結(jié)構(gòu)&字節(jié)碼指令

class文件結(jié)構(gòu)

Class文件存儲的內(nèi)容稱為字節(jié)碼(ByteCode),包含了JVM指令集和符號表以及若干其他輔助信息。

class文件是一組以8位字節(jié)為基礎(chǔ)單位的二進(jìn)制流,各個(gè)數(shù)據(jù)項(xiàng)目嚴(yán)格按照順序緊湊的排列在Class文件中,中間沒有添加任何分隔符,整個(gè)Class文件中存儲的內(nèi)容幾乎全部是程序運(yùn)行的必要的數(shù)據(jù),沒有空隙存在。

當(dāng)遇到8位字節(jié)以上的空間的數(shù)據(jù)項(xiàng)時(shí),則會按照高位在前的方式分割成若干個(gè)8位字節(jié)進(jìn)行存儲。

Class文件中有兩種數(shù)據(jù)類型,分別是無符號數(shù)和表。

無符號數(shù)

無符號數(shù)屬于基本的數(shù)據(jù)類型,以u1、u2、u4、u8來表示一個(gè)字節(jié)、兩個(gè)字節(jié)...的無符號數(shù);無符號數(shù)用來描述數(shù)字、索引引用、數(shù)量值或UTF-8編碼構(gòu)成的字符串值。

表是由多個(gè)無符號數(shù)或其他表作為數(shù)據(jù)項(xiàng)構(gòu)成的復(fù)合數(shù)據(jù)類型,一般以"_info"結(jié)尾,用來描述class文件的數(shù)據(jù)結(jié)構(gòu)。

特點(diǎn):節(jié)省存儲空間,提高處理性能

ClassFile { 
    u4 magic; 
    u2 minor_version; 
    u2 major_version; 
    u2 constant_pool_count; 
    cp_info constant_pool[constant_pool_count-1]; 
    u2 access_flags; 
    u2 this_class; 
    u2 super_class; 
    u2 interfaces_count; 
    u2 interfaces[interfaces_count]; 
    u2 fields_count; 
    field_info fields[fields_count]; 
    u2 methods_count; 
    method_info methods[methods_count]; 
    u2 attributes_count; 
    attribute_info attributes[attributes_count]; 
}
  • 魔數(shù)
  • Class文件版本
  • 常量池
  • 訪問標(biāo)志
  • 類索引,父類索引,接口索引集合
  • 字段表集合
  • 方法表集合
  • 屬性表集合

u2表示無符號數(shù)2個(gè)字節(jié)
u4表示無符號數(shù)4個(gè)字節(jié)

Class文件設(shè)計(jì)理念和意義

1. 魔數(shù)magic

魔數(shù)的唯一作用是確定這個(gè)文件是否為一個(gè)能被虛擬機(jī)所接受的Class文件。魔數(shù)值固定為0xCAFEBABE,不會改變。

證明magic作用

創(chuàng)建一個(gè)class文件 magic.class ,內(nèi)容是magic test,直接運(yùn)行java magic操作:

84407@FantJ MINGW64 ~/Desktop
$ java magictest
????: ???????? magictest ????? LinkageError
        java.lang.ClassFormatError: Incompatible magic value 1886741100 in class file magictest

報(bào)錯(cuò)意思是:magic矛盾,然后給了個(gè)magic value的十進(jìn)制數(shù),那么可以識別的magic十進(jìn)制應(yīng)該是多少呢。


應(yīng)該是3405691582

那么,然后我用javac編譯的正常java文件生成class文件,用binary viewer 查看:


minor_version、major_version

魔數(shù)往后后面四位:表示字節(jié)碼版本,分別表示Class文件的副、主版本。當(dāng)今用的最廣的幾個(gè)版本:
jdk1.8:52
jdk1.7:51
jdk1.6:50




對應(yīng)版本號是52,是jdk1.8


版本向下兼容

2. constant_pool_count

常量池計(jì)數(shù)器,值等于constant_pool表中的成員數(shù)加1,占用兩個(gè)字節(jié)

3. constant_pool[]常量池

Java虛擬機(jī)指令執(zhí)行時(shí)依賴常量池(constant_pool)表中的符號信息。

所有的常量池項(xiàng)都具有如下通用格式:

cp_info {
    u1 tag; 
    u1 info[]; 
}

info[]項(xiàng)的內(nèi)容tag由的類型所決定。tag有效的類型和對應(yīng)的取值在下表列出

常量類型
CONSTANT_Class 7
CONSTANT_Fieldref 9
CONSTANT_Methodref 10
CONSTANT_InterfaceMethodref 11
CONSTANT_String 8
CONSTANT_Integer 3
CONSTANT_Float 4
CONSTANT_Long 5
CONSTANT_Double 6
CONSTANT_NameAndType 12
CONSTANT_Utf8 1
CONSTANT_MethodHandle 15
CONSTANT_MethodType 16
CONSTANT_InvokeDynamic 18
3.1 CONSTANT_Class_info結(jié)構(gòu)

表示類或接口

CONSTANT_Class_info {
    u1 tag; 
    u2 name_index;
}

name_index必須是對常量池的一個(gè)有效索引

3.2 CONSTANT_Fieldref_info, CONSTANT_Methodref_info和CONSTANT_InterfaceMethodref_info結(jié)構(gòu)

字段:

CONSTANT_Fieldref_info {
    u1 tag; 
    u2 class_index; 
    u2 name_and_type_index; 
}

方法:

CONSTANT_Methodref_info { 
    u1 tag; 
    u2 class_index; 
    u2 name_and_type_index; 
}

接口方法:

CONSTANT_InterfaceMethodref_info {
    u1 tag; 
    u2 class_index; 
    u2 name_and_type_index; 
}

class_index必須是對常量池的有效索引,常量池在該索引處的項(xiàng)必須是CONSTANT_Class_info結(jié)構(gòu),表示一個(gè)類或接口,當(dāng)前字段或方法是這個(gè)類或接口的成員。

CONSTANT_Methodref_info結(jié)構(gòu)的class_index項(xiàng)的類型必須是類(不能是接口)。CONSTANT_InterfaceMethodref_info結(jié)構(gòu)的class_index項(xiàng)的類型必須是接口(不能是類)。CONSTANT_Fieldref_info結(jié)構(gòu)的class_index項(xiàng)的類型既可以是類也可以是接口。

name_and_type_index必須是對常量池的有效索引,表示當(dāng)前字段或方法的名字和描述符。
在一個(gè)CONSTANT_Fieldref_info結(jié)構(gòu)中,給定的描述符必須是字段描述符。而CONSTANT_Methodref_infoCONSTANT_InterfaceMethodref_info中給定的描述符必須是方法描述符。

3.3 CONSTANT_String_info結(jié)構(gòu)

用來表示String的結(jié)構(gòu)

CONSTANT_String_info {
    u1 tag;
    u2 string_index;
}

string_index必須是對常量池的有效索引,常量池在該索引處的項(xiàng)必須是CONSTANT_Utf8_info
結(jié)構(gòu),表示一組Unicode碼點(diǎn)序列,這組Unicode碼點(diǎn)序列最終會被初始化為一個(gè)String對象。

3.4CONSTANT_Integer_info和CONSTANT_Float_info結(jié)構(gòu)

表示4字節(jié)(int和float)的數(shù)值常量:

CONSTANT_Integer_info {
    u1 tag; 
    u4 bytes; 
} 
CONSTANT_Float_info { 
    u1 tag; 
    u4 bytes;
}
3.5CONSTANT_Long_info和CONSTANT_Double_info結(jié)構(gòu)

表示8字節(jié)(long和double)的數(shù)值常量

CONSTANT_Long_info {
    u1 tag; 
    u4 high_bytes; 
    u4 low_bytes; 
} 

CONSTANT_Double_info { 
    u1 tag; 
    u4 high_bytes; 
    u4 low_bytes; 
}
3.6 CONSTANT_NameAndType_info結(jié)構(gòu)

表示字段或方法,但是和前面介紹的3個(gè)結(jié)構(gòu)不同,CONSTANT_NameAndType_info結(jié)構(gòu)沒有標(biāo)識出它所屬的類或接口

CONSTANT_NameAndType_info { 
    u1 tag; 
    u2 name_index; 
    u2 descriptor_index;
}

name_index項(xiàng)的值必須是對常量池的有效索引,常量池在該索引處的項(xiàng)必須是CONSTANT_Utf8_info結(jié)構(gòu),這個(gè)結(jié)構(gòu)要么表示特殊的方法名,要么表示一個(gè)有效的字段或方法的非限定名(Unqualified Name)。

descriptor_index項(xiàng)的值必須是對常量池的有效索引,常量池在該索引處的項(xiàng)必須是CONSTANT_Utf8_info結(jié)構(gòu),這個(gè)結(jié)構(gòu)表示一個(gè)有效的字段描述符或方法描述符。

3.7 CONSTANT_Utf8_info結(jié)構(gòu)

用于表示字符串常量的值

CONSTANT_Utf8_info {
    u1 tag; 
    u2 length; 
    u1 bytes[length]; 
}

CONSTANT_Utf8_info結(jié)構(gòu)中的內(nèi)容是以length屬性確定長度的

3.8 CONSTANT_MethodHandle_info結(jié)構(gòu)

表示方法句柄

CONSTANT_MethodHandle_info {
    u1 tag;
    u1 reference_kind;
    u2 reference_index;
}

reference_kind項(xiàng)的值必須在1至9之間(包括1和9),它決定了方法句柄的類型。

  1. 如果reference_kind項(xiàng)的值為1(REF_getField)、2(REF_getStatic)、3(REF_putField)或4(REF_putStatic),那么常量池在reference_index索引處的項(xiàng)必須是CONSTANT_Fieldref_info結(jié)構(gòu),表示由一個(gè)字段創(chuàng)建的方法句柄。
  2. 如果reference_kind項(xiàng)的值是5(REF_invokeVirtual)、6(REF_invokeStatic)、7(REF_invokeSpecial)或8(REF_newInvokeSpecial),那么常量池在reference_index索引處的項(xiàng)必須是CONSTANT_Methodref_info結(jié)構(gòu),表示由類的方法或構(gòu)造函數(shù)創(chuàng)建的方法句柄。
  3. 如果reference_kind項(xiàng)的值是9(REF_invokeInterface),那么常量池在reference_index索引處的項(xiàng)必須是CONSTANT_InterfaceMethodref_info結(jié)構(gòu),表示由接口方法創(chuàng)建的方法句柄。
  4. 如果reference_kind項(xiàng)的值是5(REF_invokeVirtual)、6(REF_invokeStatic)、7(REF_invokeSpecial)或9(REF_invokeInterface),那么方法句柄對應(yīng)的方法不能為實(shí)例初始化()方法或類初始化方法()。
  5. 如果reference_kind項(xiàng)的值是8(REF_newInvokeSpecial),那么方法句柄對應(yīng)的方法必須為實(shí)例初始化()方法。
3.9 CONSTANT_MethodType_info結(jié)構(gòu)

表示方法類型

CONSTANT_MethodType_info { 
    u1 tag; 
    u2 descriptor_index; 
}
3.10 CONSTANT_InvokeDynamic_info結(jié)構(gòu)

表示invokedynamic指令所使用到的引導(dǎo)方法(Bootstrap Method)、引導(dǎo)方法使用到動態(tài)調(diào)用名稱(Dynamic Invocation Name)、參數(shù)和請求返回類型、以及可以選擇性的附加被稱為靜態(tài)參數(shù)(Static Arguments)的常量序列。

CONSTANT_InvokeDynamic_info { 
    u1 tag; 
    u2 bootstrap_method_attr_index; 
    u2 name_and_type_index; 
}

bootstrap_method_attr_index項(xiàng)的值必須是對當(dāng)前Class文件中引導(dǎo)方法表的bootstrap_methods[]數(shù)組的有效索引。

name_and_type_index項(xiàng)的值必須是對當(dāng)前常量池的有效索引,常量池在該索引處的項(xiàng)必須是CONSTANT_NameAndType_info結(jié)構(gòu),表示方法名和方法描述符。

4. access_flags:訪問標(biāo)志

訪問標(biāo)志,access_flags是一種掩碼標(biāo)志,用于表示某個(gè)類或者接口的訪問權(quán)限及基礎(chǔ)屬性。access_flags的取值范圍和相應(yīng)含義見下表。

標(biāo)記名 含義
ACC_PUBLIC 0x0001 可以被包的類外訪問。
ACC_FINAL 0x0010 不允許有子類。
ACC_SUPER 0x0020 當(dāng)用到invokespecial指令時(shí),需要特殊處理的父類方法。
ACC_INTERFACE 0x0200 標(biāo)識定義的是接口而不是類。
ACC_ABSTRACT 0x0400 不能被實(shí)例化。
ACC_SYNTHETIC 0x1000 標(biāo)識并非Java源碼生成的代碼。
ACC_ANNOTATION 0x2000 標(biāo)識注解類型
ACC_ENUM 0x4000 標(biāo)識枚舉類型

5. this_class:類索引

this_class的值必須是對constant_pool表中項(xiàng)目的一個(gè)有效索引值。

是一個(gè)對constant_pool表中項(xiàng)目的一個(gè)有效索引值,表示指向常量池的第幾個(gè)位置。

6. super_class:父類索引

表示這個(gè)Class文件所定義的類的直接父類,如果Class文件的super_class的值為0,那這個(gè)Class文件只可能是定義的是java.lang.Object類,只有它是唯一沒有父類的類

是一個(gè)對constant_pool表中項(xiàng)目的一個(gè)有效索引值,表示指向常量池的第幾個(gè)位置。

7. interfaces_count:接口計(jì)數(shù)器

表示有這個(gè)類有幾個(gè)接口。

8. interfaces[]:接口表

成員所表示的接口順序和對應(yīng)的源代碼中給定的接口順序(從左至右)一樣,即interfaces[0]對應(yīng)的是源代碼中最左邊的接口。

是一個(gè)對constant_pool表中項(xiàng)目的一個(gè)有效索引值,表示指向常量池的第幾個(gè)位置。

表示當(dāng)前類或接口的直接父接口數(shù)量

9. fields_count:字段計(jì)數(shù)器

表示當(dāng)前Class文件fields[]數(shù)組的成員個(gè)數(shù)

10. fields[]:字段表

每個(gè)成員都必須是一個(gè)fields_info結(jié)構(gòu)的數(shù)據(jù)項(xiàng),描述當(dāng)前類或接口聲明的所有字段,但不包括從父類或父接口繼承的部分。

用于表示當(dāng)前類或接口中某個(gè)字段的完整描述

field_info {
    u2 access_flags; 
    u2 name_index;      //對常量池的一個(gè)有效索引
    u2 descriptor_index;     //對常量池的一個(gè)有效索引
    u2 attributes_count;     //當(dāng)前字段的附加屬性的數(shù)量
    attribute_info attributes[attributes_count];
}

access_flags項(xiàng)的值是用于定義字段被訪問權(quán)限和基礎(chǔ)屬性的掩碼標(biāo)志。access_flags的取值范圍和相應(yīng)含義見下表所示:

標(biāo)記名 說明
ACC_PUBLIC 0x0001 public,表示字段可以從任何包訪問。
ACC_PRIVATE 0x0002 private,表示字段僅能該類自身調(diào)用。
ACC_PROTECTED 0x0004 protected,表示字段可以被子類調(diào)用。
ACC_STATIC 0x0008 static,表示靜態(tài)字段。
ACC_FINAL 0x0010 final,表示字段定義后值無法修改。
ACC_VOLATILE 0x0040 volatile,表示字段是易變的。
ACC_TRANSIENT 0x0080 transient,表示字段不會被序列化。
ACC_SYNTHETIC 0x1000 表示字段由編譯器自動產(chǎn)生。
ACC_ENUM 0x4000 enum,表示字段為枚舉類型。

attributes表的每一個(gè)成員的值必須是attribute結(jié)構(gòu),一個(gè)字段可以有任意個(gè)關(guān)聯(lián)屬性。

11. methods_count:方法計(jì)數(shù)器

methods_count的值表示當(dāng)前Class文件methods[]數(shù)組的成員個(gè)數(shù),Methods[]數(shù)組中每一項(xiàng)都是一個(gè)method_info結(jié)構(gòu)的數(shù)據(jù)項(xiàng)。

12. methods[]:方法表

method_info結(jié)構(gòu)可以表示類和接口中定義的所有方法,包括實(shí)例方法、類方法、實(shí)例初始化方法方法和類或接口初始化方法方法。methods[]數(shù)組只描述當(dāng)前類或接口中聲明的方法,不包括從父類或父接口繼承的方法。

methods[]數(shù)組中的每個(gè)成員都必須是一個(gè)method_info結(jié)構(gòu)的數(shù)據(jù)項(xiàng),用于表示當(dāng)前類或接口中某個(gè)方法的完整描述。

method_info { 
    u2 access_flags; 
    u2 name_index; 
    u2 descriptor_index; 
    u2 attributes_count; 
    attribute_info attributes[attributes_count]; 
}

access_flags項(xiàng)的值是用于定義當(dāng)前方法的訪問權(quán)限和基本屬性的掩碼標(biāo)志,access_flags的取值范圍和相應(yīng)含義見下表所示。

標(biāo)記名 說明
ACC_PUBLIC 0x0001 public,方法可以從包外訪問
ACC_PRIVATE 0x0002 private,方法只能本類中訪問
ACC_PROTECTED 0x0004 protected,方法在自身和子類可以訪問
ACC_STATIC 0x0008 static,靜態(tài)方法
ACC_FINAL 0x0010 final,方法不能被重寫(覆蓋)
ACC_SYNCHRONIZED 0x0020 synchronized,方法由管程同步
ACC_BRIDGE 0x0040 bridge,方法由編譯器產(chǎn)生
ACC_VARARGS 0x0080 表示方法帶有變長參數(shù)
ACC_NATIVE 0x0100 native,方法引用非java語言的本地方法
ACC_ABSTRACT 0x0400 abstract,方法沒有具體實(shí)現(xiàn)
ACC_STRICT 0x0800 strictfp,方法使用FP-strict浮點(diǎn)格式
ACC_SYNTHETIC 0x1000 方法在源文件中不出現(xiàn),由編譯器產(chǎn)生

name_indexdescriptor_index 兩屬性是對常量池的一個(gè)有效索引
attributes_count的項(xiàng)的值表示這個(gè)方法的附加屬性的數(shù)量。
attributes 表的每一個(gè)成員的值必須是attribute結(jié)構(gòu),一個(gè)方法可以有任意個(gè)與之相關(guān)的屬性。

13. attributes_count:屬性計(jì)數(shù)器

attributes表中每一項(xiàng)都是一個(gè)attribute_info結(jié)構(gòu)的數(shù)據(jù)項(xiàng)。

attributes_count的值表示當(dāng)前Class文件attributes表的成員個(gè)數(shù)。

14. attributes[]:屬性表

attributes表的每個(gè)項(xiàng)的值必須是attribute_info結(jié)構(gòu),在Class文件格式中的ClassFile結(jié)構(gòu)、field_info結(jié)構(gòu),method_info結(jié)構(gòu)和Code_attribute結(jié)構(gòu)都有使用,所有屬性的通用格式如下:

attribute_info {
    u2 attribute_name_index; 
    u4 attribute_length; 
    u1 info[attribute_length];
}

attribute_name_index必須是對當(dāng)前Class文件的常量池的有效16位無符號索引。表示當(dāng)前屬性的名字。

attribute_length項(xiàng)的值給出了跟隨其后的字節(jié)的長度,這個(gè)長度不包括attribute_name_indexattribute_name_index項(xiàng)的6個(gè)字節(jié)。

14.1 ConstantValue屬性

ConstantValue屬性是定長屬性,位于field_info結(jié)構(gòu)的屬性表中。如果該字段為靜態(tài)類型(即field_info結(jié)構(gòu)的access_flags項(xiàng)設(shè)置了ACC_STATIC標(biāo)志),則說明這個(gè)field_info結(jié)構(gòu)表示的常量字段值將被分配為它的ConstantValue屬性表示的值,這個(gè)過程也是類或接口申明的常量字段(Constant Field)初始化的一部分。這個(gè)過程發(fā)生在引用類或接口的類初始化方法執(zhí)行之前。

ConstantValue_attribute { 
    u2 attribute_name_index; 
    u4 attribute_length; 
    u2 constantvalue_index; 
}

attribute_name_index項(xiàng)的值,必須是一個(gè)對常量池的有效索引。
attribute_length項(xiàng)的值固定為2。
constantvalue_index項(xiàng)的值,必須是一個(gè)對常量池的有效索引。

14.2 Code屬性

Code屬性是一個(gè)變長屬性,位于method_info結(jié)構(gòu)的屬性表。一個(gè)Code屬性只為唯一一個(gè)方法、實(shí)例類初始化方法或類初始化方法保存Java虛擬機(jī)指令及相關(guān)輔助信息。所有Java虛擬機(jī)實(shí)現(xiàn)都必須能夠識別Code屬性。如果方法被聲明為native或者abstract類型,那么對應(yīng)的method_info結(jié)構(gòu)不能有明確的Code屬性,其它情況下,method_info有必須有明確的Code屬性。

Code_attribute {
    u2 attribute_name_index;
    u4 attribute_length; 
    u2 max_stack;
    u2 max_locals;
    u4 code_length; 
    u1 code[code_length]; 
    u2 exception_table_length; 
    {   u2 start_pc;
        u2 end_pc; 
        u2 handler_pc; 
        u2 catch_type; 
    } exception_table[exception_table_length]; 
    u2 attributes_count; 
    attribute_info attributes[attributes_count];
}

attribute_name_index項(xiàng)的值必須是對常量池的有效索引
attribute_length項(xiàng)的值表示當(dāng)前屬性的長度,不包括開始的6個(gè)字節(jié)。
max_stack項(xiàng)的值給出了當(dāng)前方法的操作數(shù)棧在運(yùn)行執(zhí)行的任何時(shí)間點(diǎn)的最大深度。
max_locals項(xiàng)的值給出了分配在當(dāng)前方法引用的局部變量表中的局部變量個(gè)數(shù),包括調(diào)用此方法時(shí)用于傳遞參數(shù)的局部變量。long和double型的局部變量的最大索引是max_locals-2,其它類型的局部變量的最大索引是max_locals-1.
code_length項(xiàng)給出了當(dāng)前方法的code[]數(shù)組的字節(jié)數(shù),code_length的值必須大于0,即code[]數(shù)組不能為空。
code[]數(shù)組給出了實(shí)現(xiàn)當(dāng)前方法的Java虛擬機(jī)字節(jié)碼。
exception_table_length項(xiàng)的值給出了exception_table[]數(shù)組的成員個(gè)數(shù)量。
exception_table[]數(shù)組的每個(gè)成員表示code[]數(shù)組中的一個(gè)異常處理器(Exception Handler)。exception_table[]數(shù)組中,異常處理器順序是有意義的(不能隨意更改)。
start_pcend_pc兩項(xiàng)的值表明了異常處理器在code[]數(shù)組中的有效范圍。
handler_pc項(xiàng)表示一個(gè)異常處理器的起點(diǎn)
如果catch_type項(xiàng)的值不為0,那么它必須是對常量池的一個(gè)有效索引
attributes_count項(xiàng)的值給出了Code屬性中attributes表的成員個(gè)數(shù)。
屬性表的每個(gè)成員的值必須是attribute結(jié)構(gòu)。一個(gè)Code屬性可以有任意數(shù)量的可選屬性與之關(guān)聯(lián)。

14.3 StackMapTable屬性

StackMapTable屬性是一個(gè)變長屬性,位于Code屬性的屬性表中。這個(gè)屬性會在虛擬機(jī)類加載的類型階段被使用。

StackMapTable_attribute { 
    u2 attribute_name_index;
    u4 attribute_length; 
    u2 number_of_entries; 
    stack_map_frame entries[number_of_entries];
}

attribute_name_index項(xiàng)的值必須是對常量池的有效索引
attribute_length項(xiàng)的值表示當(dāng)前屬性的長度,不包括開始的6個(gè)字節(jié)。
number_of_entries項(xiàng)的值給出了entries表中的成員數(shù)量。Entries表的每個(gè)成員是都是一個(gè)stack_map_frame結(jié)構(gòu)的項(xiàng)。
entries表給出了當(dāng)前方法所需的stack_map_frame結(jié)構(gòu)。

...更多的屬性就不在這一一貼了,太多了,需要的時(shí)候查官方文檔即可:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4

字節(jié)碼指令

java虛擬機(jī)指令由一個(gè)字節(jié)長度的,代表某種特定操作含義的數(shù)字(稱之為操作碼),以及隨后的代表此操作所需參數(shù)的操作數(shù)而構(gòu)成。

操作碼的長度為1個(gè)字節(jié),所以最大只有256條

常量入棧指令
局部變量值轉(zhuǎn)載到棧中指令
將棧頂值保存到局部變量中指令
wide指令
通用(無類型)棧操作指令
類型轉(zhuǎn)換指令
整數(shù)運(yùn)算
浮點(diǎn)運(yùn)算
邏輯運(yùn)算——移位運(yùn)算
邏輯運(yùn)算——按位布爾運(yùn)算
控制流指令——條件跳轉(zhuǎn)指令
控制流指令——比較指令
控制流指令——無條件跳轉(zhuǎn)指令
控制流指令——表跳轉(zhuǎn)指令
控制流指令——異常和finally
對象操作指令
數(shù)組操作指令
方法調(diào)用指令
方法返回指令
線程同步指令

指令參考:https://blog.csdn.net/web_code/article/details/12164733

一個(gè)簡單的demo分析

Test.java

public class Test {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int c = a+b;
        System.out.println(c);
    }
}

javap -v Test.class

   #2 = Fieldref           #24.#25        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = Methodref          #26.#27        // java/io/PrintStream.println:(I)V
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=1
         0: bipush        10    //把10擴(kuò)展成int入棧
         2: istore_1      //將棧頂int類型值保存到局部變量1中
         3: bipush        20     //把20擴(kuò)展成int入棧
         5: istore_2     //將棧頂int類型值保存到局部變量2中
         6: iload_1      //從局部變量1中裝載int類型值入棧  
         7: iload_2     //從局部變量2中裝載int類型值入棧  
         8: iadd       // 將棧頂兩int類型數(shù)相加,結(jié)果入棧。
         9: istore_3     //將棧頂int類型值保存到局部變量3中
        10: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;獲取靜態(tài)字段的值。#2表示常量池的索引
        13: iload_3
        14: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V 運(yùn)行時(shí)方法綁定調(diào)用方法。
        17: return      //void函數(shù)返回。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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