java編程學(xué)習(xí):深入理解JVM之Java字節(jié)碼文件

Java是一種可以撰寫跨平臺應(yīng)用軟件的面向?qū)ο蟮某绦蛟O(shè)計(jì)語言。Java 技術(shù)具有卓越的通用性、高效性、平臺移植性和安全性,廣泛應(yīng)用于PC、數(shù)據(jù)中心、游戲控制臺、科學(xué)超級計(jì)算機(jī)、移動電話和互聯(lián)網(wǎng),同時擁有全球最大的開發(fā)者專業(yè)社群。

給你學(xué)習(xí)路線:html-css-js-jq-javase-數(shù)據(jù)庫-jsp-servlet-Struts2-hibernate-mybatis-spring4-springmvc-ssh-ssm

每一個class字節(jié)碼文件都唯一對應(yīng)一個類或接口,class文件中記錄中類或接口的基本信息,但反之不成立,不是每一個類或接口都有一個唯一對應(yīng)的字節(jié)碼文件,首先類或接口的字節(jié)碼可以不以文件的方式存儲,可以直接從內(nèi)存中生成字節(jié)碼,而不產(chǎn)生.class文件,動態(tài)代理的原理就是直接內(nèi)存中生成字節(jié)碼流,根據(jù)加載字節(jié)碼流進(jìn)行類加載操作,類實(shí)例化,生成代理對象。

小編推薦一個學(xué)Java的學(xué)習(xí)裙【 七六零,二五零,五四一 】,無論你是大牛還是小白,是想轉(zhuǎn)行還是想入行都可以來了解一起進(jìn)步一起學(xué)習(xí)!裙內(nèi)有開發(fā)工具,很多干貨和技術(shù)資料分享!

字節(jié)碼文件記錄的信息:魔術(shù),class文件主次版本,常量池?cái)?shù)量及常量池表,類或接口的訪問標(biāo)志,類索引,超類索引,接口數(shù)量及接口表,字段數(shù)量及字段表,方法數(shù)量及方法表,屬性屬性及屬性表,jvm中使用類c結(jié)構(gòu)體表示每一種屬性,結(jié)構(gòu)體中類型種類有兩種,無符號數(shù)及表,以 _info結(jié)尾表示表,以 u1,u2,u4,u8分別表示1字節(jié),2字節(jié),4字節(jié),8字節(jié)無符號數(shù)

ClassFile{

u4 magic;

u2 minor_version;

u2 major_version;

u2 constant_pool_count;

cp_info constant_pool[constant_pool_count];

u2 acc_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ù):四個字節(jié),用于定義此字節(jié)碼文件是否符合虛擬機(jī)規(guī)范,保證字節(jié)碼文件不會威脅虛擬機(jī)的安全,若為cafebabe則表示字節(jié)碼符合虛擬機(jī)規(guī)范

主次版本號:四個字節(jié),前兩字節(jié)表示次版本號,后兩字節(jié)表示主版本號,用于定義編譯的字節(jié)碼文件格式版本,低版本虛擬機(jī)拒絕運(yùn)行高版本字節(jié)碼文件,但高版本虛擬機(jī)會向下兼容低版本字節(jié)碼文件

常量池?cái)?shù)量及常量池表:這部分主要統(tǒng)計(jì)類或接口的字面量和符號引用,用于每個類或接口擁有的字面量和符號引用屬性不一定相同,所有需要兩個字節(jié)的長度來表示常量池?cái)?shù)目,常量池?cái)?shù)目計(jì)數(shù)從1開始,比如類或接口中總共有兩個字面量符號引用,則常量池?cái)?shù)目為2,注意,不是從0開始計(jì)數(shù),0可能另有用處,可以用來表示類或接口中未出現(xiàn)的引用,用來表示超級父類java.long.Object全限定名的索引,常量池表是一個數(shù)組,一共有18種類型,每一種類型有一個tag屬性與之對應(yīng),constant_utf8_info用于表示文本字符串,類和接口全限定名,字段名稱及描述符,方法名稱及描述符等常量信息,constant_integer_info用于存儲int類型的常量信息,只存儲int類型的值,不存儲其他符合引用信息,比如 final int a=1 符號引用信息為a,值為1,constant_float_info用于存儲float類型常量信息,也是只存儲float值,不存儲引用信息,constant_long_info用于存儲long類型的常量信息,constant_double_info用于存儲double類型的常量信息,constant_class_info用于存儲指向常量池列表constant_unf8_info類和接口全限定名的有效引用,constant_string_info用于存儲指定常量池列表constant_utf8_info某常量項(xiàng)的有效索引,指向文本字符串,constant_fieldref_info用于存儲指向常量池列表constant_class_info常量項(xiàng)和constant_nameandtype_info常量項(xiàng)的有效索引,constant_methodref_info用于存儲指向常量池列表constant_class_info常量項(xiàng)和constant_nameandtype_info常量項(xiàng)的有效索引,constant_interfacemethodref_info用于存儲指向常量池列表constant_class_info常量項(xiàng)和constant_nameandtype_info常量項(xiàng)的有效索引,constant_nameandtype_info用于存儲指向常量池列表constant_utf8_info常量項(xiàng)的有效索引,可以通過所有找到對應(yīng)類及描述符,constant_methodtype_info用于存儲指向常量池constant_utf8_info常量項(xiàng),表示方法類型,找到對應(yīng)的方法描述符,constant_methodhandle_info用于表示方法句柄,屬性reference_kind表示方法句柄的類型,1-4表示為字段創(chuàng)建的方法句柄,5-8表示為類方法(構(gòu)造、實(shí)例、靜態(tài))創(chuàng)建的句柄,9表示為接口方法創(chuàng)建的句柄,reference_index屬性指向根據(jù)reference_kind對應(yīng)的常量池列表,constant_invokedynamic_info用于存儲當(dāng)前字節(jié)碼文件中引導(dǎo)方法bootstrap_method數(shù)組的有效索引和指向常量池constant_nameandtype_info常量項(xiàng)的有效索引

constant_utf8_info{

u1 tag;

u2 length;

u1 bytes[length];

}

constant_integer_info{

u1 tag;

u4 bytes;

}

constant_float_info{

u1 tag;

u4 float;

}

constant_long_info{

u1 falg;

u8 long;

}

constant_double_info{

u1 tag;

u4 double;

}

constant_class_info{

u1 tag;

u2 name_index;

}

constant_string_info{

u1 tag;

u2 string_index;

}

constant_fieldref_info{

u1 tag;

u2 class_index;

u2 name_and_type_index;

}

constant_mathodref_info{

u1 tag;

u2 class_index;

u2 name_and_type_index;

}

constant_interfacemathodref_info{

u1 tag;

u2 class_index;

u2 name_and_type_index;

}

小編推薦一個學(xué)Java的學(xué)習(xí)裙【 七六零,二五零,五四一 】,無論你是大牛還是小白,是想轉(zhuǎn)行還是想入行都可以來了解一起進(jìn)步一起學(xué)習(xí)!裙內(nèi)有開發(fā)工具,很多干貨和技術(shù)資料分享!

constant_nameandtype_info{

u1 tag;

u2 class_index;

u2 descriptor_index;

}

constant_methodhandle_info{

u1 tag;

u2 reference_kind;

u2 reference_index;

}

constant_methodtype_info{

u1 tag;

u2 descriptor_index;

}

constant_invokedynamic_info{

u1 tag;

u2 bootstrap_method_attr_index;

u2 name_and_type_index;

}

訪問標(biāo)志:兩個字節(jié),用于定義字節(jié)碼文件所表示的類或接口的訪問權(quán)限,如判斷是類還是接口,類是否被abstract修飾,類是否被final修飾, acc_interface表示是接口,acc_annotation表示是注解類型,acc_enum表示是枚舉類型,acc_public 表示類或接口是public訪問權(quán)限,acc_final表示類不允許被繼承,acc_abstract表示類為抽象類,acc_super表示類調(diào)用實(shí)例方法時需進(jìn)行特殊操作

類索引及父類索引:四個字節(jié),用于存儲指向常量池constant_class_info對應(yīng)的有效索引,而constant_class_info存儲常量池列表的constant_utf8_info常量項(xiàng)索引,根據(jù)此索引可找到類和父類的全限定名

接口數(shù)量及接口表:接口屬性用于存儲當(dāng)前類或接口的直接超類接口數(shù)量,接口表是一個數(shù)組,記住,只有常量池表從1開始計(jì)數(shù),其余都是從數(shù)組下表0開始計(jì)數(shù),接口表數(shù)組的每一個數(shù)組元素存儲此類或接口的直接超類接口的有效索引,根據(jù)此索引找到constant_class_info對應(yīng)的常量項(xiàng),根據(jù)constant_class_info可找到對應(yīng)直接超類接口的全限定名

字段數(shù)量及字段表:字段數(shù)量用于存儲類或接口的字段數(shù)目,包括類字段和實(shí)例字段,字段表為一個數(shù)組,每一個數(shù)組元素都相當(dāng)于一個field_info結(jié)構(gòu)的對象,field_info結(jié)構(gòu)包含字段完整信息:字段標(biāo)識符,字段訪問修飾符,字段是類字段還是實(shí)例字段,字段是否為常量等,注意:此處字段表示當(dāng)前類或接口的字段,不包括從超類或接口繼承的字段,java語法規(guī)范不允許同一個類或接口中出現(xiàn)同一字段名的不同字段,但是class文件中卻可以允許出現(xiàn)相同字段名的不同字段,只有字段的描述符不同即可,field_info結(jié)構(gòu)屬性:access_flags用于存儲字段的訪問標(biāo)志,acc_private,acc_protected,acc_public,acc_final,acc_static,acc_volatile等,注意:acc_final與acc_volatile不能同時出現(xiàn)在同一字段,name_index指向常量池constant_utf8_info常量項(xiàng)的有效索引,獲取當(dāng)前字段的簡單名稱,descriptor_index指向常量池constant_utf8_info常量項(xiàng)的有效索引,獲取當(dāng)前字段的描述符,attribute_count,attributes[attributes_count]這兩項(xiàng)表示字段的屬性信息,用于描述字段相關(guān)信息,attribute數(shù)組每一個元素都是一個attribute_info結(jié)構(gòu)的元素

field_info{

u2 access_flags;

u2 name_index;

u2 descriptor_index;

u2 attributes_count;

attribute_info attributes[attribuyes_count];

}

方法數(shù)量及方法表:方法數(shù)量用于存儲當(dāng)前類或接口的方法數(shù)目,包括實(shí)例方法,類方法,抽象方法,方法表是一個數(shù)組,每一個數(shù)組元素都是一個method_info結(jié)構(gòu),method_info結(jié)構(gòu)包含方法的完整信息:方法描述符,訪問修飾符,是否為final方法,是否為abstract方法等,注意:此處的方法數(shù)組只是表示當(dāng)前類或接口的所有方法,并不包括從超類及父接口繼承來的方法,java語法規(guī)范java類或接口中不允許出現(xiàn)方法簽名完全一樣的方法同時出現(xiàn),會編譯報(bào)錯,而字節(jié)碼層面卻允許方法簽名完全相同的方法同時出現(xiàn),只需要保證方法的返回值類型不同,method_info結(jié)構(gòu)屬性與field_info一致,但acc_flags類型不盡相同,注意acc_abstract不能與acc_final,acc_static,acc_private,acc_synchronized,acc_native同時使用,接口方法中只能使用acc_public,acc_abstract,此處我有一個疑問,接口中default方法有沒有對應(yīng)的訪問標(biāo)志,注意:方法只能使用acc_private,acc_protected,acc_public訪問標(biāo)志

method_info{

u2 access_flags;

u2 name_index;

u2 descriptor_index;

u2 attributes_count;

attribute_info attributes[attribuyes_count];

}

屬性數(shù)量及屬性表:屬性數(shù)量表示當(dāng)前字節(jié)碼文件中attribute_info表數(shù)目,屬性表是一個數(shù)組,每一個數(shù)組元素都是attribute_info結(jié)構(gòu),attribute_info結(jié)構(gòu)表示屬性的完整信息:第一項(xiàng)指向常量池constant_utf8_info某常量項(xiàng)的有效索引,根據(jù)此索引可找到屬性對應(yīng)名稱,屬性可以出現(xiàn)在classFile,字段表,方法表中,用以描述相關(guān)信息,attribute_info結(jié)構(gòu)完整信息:attribute_name_index指向常量池constant_utf8_info常量項(xiàng)的有效索引,獲取屬性名稱,attribute_length用于指明info數(shù)組長度,info[attribute_length]用于存儲屬性的數(shù)據(jù)信息,必須實(shí)現(xiàn)的數(shù)據(jù)信息:Code,ConstantValue,Exceptions, code屬性用于描述method_info的具體相關(guān)信息,attribute_name_index指向常量池constant_utf8_info常量項(xiàng)的有效索引,獲取屬性名稱,即code,attribute_length表示attribute表示attribute_info長度,不包括attribute_name_index和attribute_length的初始6字節(jié),max_stack描述當(dāng)前方法最大棧深度,max_locals描述當(dāng)前方法的局部變量表,code_length表示code數(shù)組長度,code[]表示當(dāng)前方法編譯后的字節(jié)碼, ContantVaue位于field_info結(jié)構(gòu)中,用于通知虛擬機(jī)對類變量進(jìn)行初始化,即字段需要被acc_static修飾,當(dāng)前類常量不需要ContantValue通知虛擬機(jī)執(zhí)行初始化,早就執(zhí)行好了,實(shí)例字段此時不需要初始化

attribute_info{

u2 attribute_name_index;

u4 attribute_length;

u1 info[attribute_length];

}

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;

exception_info exception_table[exception_table_length];

u2 attributes_count;

attribute_info attributes[attributes_count];

}

constantvalue_attribute{

u2 attribute_name_index;

u4 attribute_length;

u2 constantvalue_index;

}

小編推薦一個學(xué)Java的學(xué)習(xí)裙【 七六零,二五零,五四一 】,無論你是大牛還是小白,是想轉(zhuǎn)行還是想入行都可以來了解一起進(jìn)步一起學(xué)習(xí)!裙內(nèi)有開發(fā)工具,很多干貨和技術(shù)資料分享!

簡單名稱與描述符:

簡單名稱是指字段或方法的簡單的一種描述,比如person class:private String name字段簡單名稱為name,Object class:public String toString()方法簡單名稱為toString,注意:字段或方法簡單名稱不允許出現(xiàn) . : / [ 等ASSIC或Unicode字符表示形式

描述符一般指字段或方法的類型,字段描述符表示字段類型描述,方法描述符表示參數(shù)描述與返回值描述,如:person class:private String name字段描述符為Ljava.lang.String,com.test.Person class:setName(String name)方法描述符為(Ljava.lang.String)V,注意:其中V表示返回值為void類型,如果參數(shù)為void則表示為()Ljava.lang.Object,表示無參的返回值為java.lang.Object引用類型的方法描述符

字段描述符解釋:B byte 字節(jié)類型,Z boolean 布爾類型,C char 字符類型,S short 短整型,I 整型,L long 長整型,F(xiàn) float 單進(jìn)度浮點(diǎn)類型,D double 雙精度浮點(diǎn)類型,L reference 對象引用類型,[ reference 數(shù)組引用類型

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

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

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