<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Class 類文件結(jié)構(gòu)

          共 4291字,需瀏覽 9分鐘

           ·

          2021-01-11 22:40

          點擊上方藍色字體,選擇“標(biāo)星公眾號”

          優(yōu)質(zhì)文章,第一時間送達

          ? 作者?|? Zzzkis

          來源 |? urlify.cn/yuAJJj

          76套java從入門到精通實戰(zhàn)課程分享

          一,概述

          我們知道,Java 具有跨平臺性,其實現(xiàn)基礎(chǔ)就是虛擬機和字節(jié)碼存儲格式。Java 虛擬機不與 Java 語言綁定,只與 Class 文件所關(guān)聯(lián)。Java 虛擬機作為一個通用的、與機器無關(guān)的執(zhí)行平臺,任何語言都可以將 Java 虛擬機作為它們的運行基礎(chǔ),以 Class 文件作為它們產(chǎn)品的交付媒介。

          Class 文件是一組以 8 個字節(jié)為基礎(chǔ)單位的二進制流,各個數(shù)據(jù)項目嚴格按照順序緊湊地排列在文件之中,中間沒有添加任何分隔符,這使得整個 Class 文件中存儲的內(nèi)容幾乎全部是程序運行的必要數(shù)據(jù)。當(dāng)遇到需占用 8 個字節(jié)以上空間的數(shù)據(jù)項時,則會按照高位在前的方式分割成若干個 8 個字節(jié)進行存儲。

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

          • 無符號數(shù)屬于基本數(shù)據(jù)類型,以 u1、u2、u4、u8 來分別代表 1 個字節(jié)、2 個字節(jié)、4 個字節(jié)和 8 個字節(jié)的無符號數(shù),無符號數(shù)可以用來描述數(shù)字、索引引用、數(shù)量值或 UTF-8 編碼構(gòu)成字符串值

          • 表是由多個無符號數(shù)或其他表作為數(shù)據(jù)項構(gòu)成的復(fù)合數(shù)據(jù)類型,一般以 _info 結(jié)尾。表用于描述有層次關(guān)系的復(fù)合結(jié)構(gòu)的數(shù)據(jù),整個 Class 文件本質(zhì)上也可以視作是一張表

          無論是無符號數(shù)還是表,當(dāng)需要描述同一類型但數(shù)量不定的多個數(shù)據(jù)時,經(jīng)常會使用一個前置的容量計數(shù)器加若干個連續(xù)的數(shù)據(jù)項的形式,這時候稱這一系列連續(xù)的某一類型的數(shù)據(jù)為某一類型的集合。

          下面是 Class 文件格式:

          類型名稱數(shù)量
          u4magic1
          u2minor_version1
          u2major_version1
          u2constant_pool_count1
          cp_infoconstant_poolconstant_pool_count - 1
          u2access_flags1
          u2this_class1
          u2super_class1
          u2interfaces_count1
          u2interfacesinterfaces_count
          u2fields_count1
          field_infofieldsfields_count
          u2methods_count1
          method_infomethodsmethods_count
          u2attribute_count1
          attribute_infoattributesattributes_count


          二,魔數(shù)和 Class 文件版本

          Class 文件的頭 4 個字節(jié)被稱為魔數(shù)(Magic Number),它的唯一作用是確定該 Class 文件是否能被虛擬機接受,其值為 0xCAFEBABE(咖啡寶貝)。

          緊接著魔數(shù)的 4 個字節(jié)存儲的是 Class 文件的版本號:第 5 和第 6 個字節(jié)是次版本號(Minor Version),第 7 和第 8 個字節(jié)是主版本號(Major Version)。Java 版本號從 45 開始,以后每個 JDK 大版本發(fā)布則主版本號加 1。高版本的 JDK 能向下兼容以前版本的 Class 文件,但不能運行以后版本的 Class 文件。



          三,常量池

          緊接著主、次版本號的是常量池入口,常量池入口需要放置一項 u2 類型的數(shù)據(jù),代表常量池容量計數(shù)值(constant_pool_count),這個容量計數(shù)是從 1 而不是從 0 開始,第 0 項用于表達“不引用任何一個常量池項目”的含義。Class 文件結(jié)構(gòu)中只有常量池的容量計數(shù)是從 1 開始,其他都是從 0 開始。

          常量池中主要存放兩大類常量:字面量和符號引用。字面量比較接近 Java 語言層面的常量概念,如文本字符串、被聲明為 final 的常量值等。而符號引用則屬于編譯原理方面的概念,主要包括下面幾類常量:

          • 被模塊導(dǎo)出或開放的包(Package)

          • 類和接口的全限定名(Fully Qualified Name)

          • 字段的名稱和描述符(Descriptor)

          • 方法的名稱和描述符

          • 方法句柄和方法類型(Method Handle、Method Type、Invoke Dynamic)

          • 動態(tài)調(diào)用點和動態(tài)常量(Dynamically-Computed Call Site、Dynamically-Computed Constant)

          Java 會在虛擬機加載 Class 文件的時候進行動態(tài)連接,將符號引用轉(zhuǎn)換為真正的內(nèi)存入口。常量池中每一項常量都是一個表,最初有 11 種結(jié)構(gòu)不同的表結(jié)構(gòu)數(shù)據(jù),后來為了更好地支持動態(tài)語言調(diào)用,額外增加了 4 種動態(tài)語言相關(guān)的常量,后來為了支持 Java 模塊化,又加入了 2 個常量,所以截止 JDK13,常量表中有 17 種不同類型的常量。這 17 類表都有一個共同的特點,表結(jié)構(gòu)起始的第一位是個 u1 類型的標(biāo)志位(tag)

          17 種常量類型所代表的具體含義如表:

          類型標(biāo)志描述
          CONSTANT_Utf8_info1UTF-8 編碼的字符串
          CONSTANT_Integer_info3整型字面量
          CONSTANT_Float_info4浮點型字面量
          CONSTANT_Long_info5長整型型字面量
          CONSTANT_Double_info6雙精度浮點型字面量
          CONSTANT_Class_info7類或接口的符號引用
          CONSTANT_String_info8字符串類型字面量
          CONSTANT_Fieldref_info9字段的符號引用
          CONSTANT_Methodref_info10類中方法的符號引用
          CONSTANT_InterfaceMethodref_info11接口中方法的符號引用
          CONSTANT_NameAndType_info12字段或方法的部分符號引用
          CONSTANT_MethodHandle_info15表示方法句柄
          CONSTANT_MethodType_info16表示方法類型
          CONSTANT_Dynamic_info17表示一個動態(tài)計算常量
          CONSTANT_InvokeDynamic_info18表示一個動態(tài)方法調(diào)用點
          CONSTANT_Moudle_info19表示一個模塊
          CONSTANT_Package_info20表示一個模塊中開放或者導(dǎo)出的包


          四,訪問標(biāo)志

          常量池結(jié)束之后,緊接著的 2 個字節(jié)代表訪問標(biāo)志(access_flags),這個標(biāo)志用于標(biāo)識一些類或者接口層次的訪問信息,包括這個 Class 是類還是接口;是否定義為 public 類型;是否定義為 abstract 類型;如果是類的話,是否被聲明為 final 等等。具體的標(biāo)志位以及標(biāo)志的含義如表:

          標(biāo)志名稱標(biāo)志值含義
          ACC_PUBLIC0x0001是否為 Public 類型
          ACC_FINAL0x0010是否被聲明為 final,只有類可以設(shè)置
          ACC_SUPER0x0020是否允許使用 invokespecial 字節(jié)碼指令的新語義
          ACC_INTERFACE0x0200標(biāo)志這是一個接口
          ACC_ABSTRACT0x0400是否為 abstract 類型,對于接口或者抽象類來說,次標(biāo)志值為真,其他類型為假
          ACC_SYNTHETIC0x1000標(biāo)志這個類并非由用戶代碼產(chǎn)生
          ACC_ANNOTATION0x2000標(biāo)志這是一個注解
          ACC_ENUM0x4000標(biāo)志這是一個枚舉

          access_flags 中一共有 16 個標(biāo)志位可以使用,當(dāng)前只定義了其中 9 個,沒有使用到的標(biāo)志位要求一律為零。


          五,類索引、父類索引與接口索引集合

          類索引(this_class)、父類索引(super_class)和接口索引(interfaces)都按順序排列在訪問標(biāo)志之后,類索引和父類索引用兩個 u2 類型的索引值表示,而接口索引是一組 u2 類型的數(shù)據(jù)的集合。

          類索引用于確定該類的全限定名,父類索引確定該類的父類的全限定名,由于 Java 不允許多繼承,因此父類索引只有一個,Object 類的父類索引為 0。類索引和父類索引各自指向一個 CONSTANT_Class_info 的類描述符常量,通過這個索引值可以找到定義在 CONSTANT_Utf8_info 類型的常量中的全限定名字符串。

          對于接口索引集合,入口的第一項 u2 類型的數(shù)據(jù)為接口計數(shù)器(interfaces_count),表示索引表的容量,如果該類沒有實現(xiàn)任何接口,則該計數(shù)器的值為 0,后面接口的索引表不再占用任何字節(jié)。


          六,字段表集合方法表集合

          字段表集合(field_info)用于描述接口或類中聲明的變量,包括類級變量以及實例級變量,但不包括在方法內(nèi)部聲明的局部變量。字段包含待信息有字段的作用域(public、private、protected)、是實例變量還是類變量(static)、可變性(final)等等。這些信息要么有,要么沒有,很適合用標(biāo)志位來表示,而字段叫什么,被定義為什么數(shù)據(jù)類型,這些都無法固定,只能用常量池中的常量來描述。

          字段表結(jié)構(gòu)如下:

          類型名稱數(shù)量
          u2access_flags1
          u2name_index1
          u2descriptor_index1
          u2attributes_count1
          attribute_infoattributesattributes_count

          access_flags 用來標(biāo)識字段修飾符(public、static、final、volatile ...),name_index 和 descriptor_index 都是對常量池的引用,分別代表字段的簡單名稱以及字段和方法的描述符。之后的是屬性表集合,用于存儲一些額外信息。

          字段表集合不會列出從父類或父接口繼承而來的字段,但有可能出現(xiàn)原本 Java 代碼中沒有的字段,例如內(nèi)部類為了保持對外部類的訪問性,編譯器會自動添加指向外部類實例的字段。

          方法表集合與字段表集合幾乎完全一致,僅在標(biāo)志和屬性表集合的可選項中有所區(qū)別。至于方法里面的代碼,則經(jīng)編譯后存放在方法屬性表集合中一個名為 Code 的屬性里面。


          粉絲福利:Java從入門到入土學(xué)習(xí)路線圖

          ??????

          ??長按上方微信二維碼?2 秒


          感謝點贊支持下哈?

          瀏覽 27
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费国产黄色视频网站 | 亚洲日韩欧美在线中文18 | 国产久久久精品1000部视频 | 色五月丁香亚洲 | 一级一片内射 |