最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java Class 解析器實(shí)現(xiàn)方法示例

 更新時(shí)間:2017年09月14日 14:21:55   作者:tinylcy  
這篇文章主要通過對(duì)class文件的分析,介紹了Java Class 解析器實(shí)現(xiàn)方法示例,具有一定參考價(jià)值,需要的朋友可以了解下。

最近在寫一個(gè)私人項(xiàng)目,名字叫做ClassAnalyzer,ClassAnalyzer的目的是能讓我們對(duì)Java Class文件的設(shè)計(jì)與結(jié)構(gòu)能夠有一個(gè)深入的理解。主體框架與基本功能已經(jīng)完成,還有一些細(xì)節(jié)功能日后再增加。實(shí)際上JDK已經(jīng)提供了命令行工具javap來反編譯Class文件,但本篇文章將闡明我實(shí)現(xiàn)解析器的思路。

Class文件

作為類或者接口信息的載體,每個(gè)Class文件都完整的定義了一個(gè)類。為了使Java程序可以“編寫一次,處處運(yùn)行”,Java虛擬機(jī)規(guī)范對(duì)Class文件進(jìn)行了嚴(yán)格的規(guī)定。構(gòu)成Class文件的基本數(shù)據(jù)單位是字節(jié),這些字節(jié)之間不存在任何分隔符,這使得整個(gè)Class文件中存儲(chǔ)的內(nèi)容幾乎全部是程序運(yùn)行的必要數(shù)據(jù),單個(gè)字節(jié)無法表示的數(shù)據(jù)由多個(gè)連續(xù)的字節(jié)來表示。

根據(jù)Java虛擬機(jī)規(guī)范,Class文件采用一種類似于C語言結(jié)構(gòu)體的偽結(jié)構(gòu)來存儲(chǔ)數(shù)據(jù),這種偽結(jié)構(gòu)中只有兩種數(shù)據(jù)類型:無符號(hào)數(shù)和表。Java虛擬機(jī)規(guī)范定義了u1、u2、u4和u8來分別表示1個(gè)字節(jié)、2個(gè)字節(jié)、4個(gè)字節(jié)和8個(gè)字節(jié)的無符號(hào)數(shù),無符號(hào)數(shù)可以用來描述數(shù)字、索引引用、數(shù)量值或者是字符串。表是由多個(gè)無符號(hào)數(shù)或者其它表作為數(shù)據(jù)項(xiàng)構(gòu)成的復(fù)合數(shù)據(jù)類型,表用于描述有層次關(guān)系的復(fù)合結(jié)構(gòu)的數(shù)據(jù),因此整個(gè)Class文件本質(zhì)上就是一張表。在ClassAnalyzer中,byte、short、int和long分別對(duì)應(yīng)u1、u2、u4和u8數(shù)據(jù)類型,Class文件被描述為如下Java類。

public class ClassFile {
 public U4 magic;       // magic
 public U2 minorVersion;      // minor_version
 public U2 majorVersion;      // major_version
 public U2 constantPoolCount;    // constant_pool_count
 public ConstantPoolInfo[] cpInfo;   // cp_info
 public U2 accessFlags;      // access_flags
 public U2 thisClass;      // this_class
 public U2 superClass;      // super_class
 public U2 interfacesCount;     // interfaces_count
 public U2[] interfaces;      // interfaces
 public U2 fieldsCount;      // fields_count
 public FieldInfo[] fields;     // fields
 public U2 methodsCount;      // methods_count
 public MethodInfo[] methods;    // methods
 public U2 attributesCount;     // attributes_count
 public BasicAttributeInfo[] attributes;  // attributes
}

如何解析

組成Class文件的各個(gè)數(shù)據(jù)項(xiàng)中,例如魔數(shù)、Class文件的版本等數(shù)據(jù)項(xiàng)、訪問標(biāo)志、類索引、父類索引,它們?cè)诿總€(gè)Class文件中都占用固定數(shù)量的字節(jié),在解析時(shí)只需要讀取相應(yīng)數(shù)量的字節(jié)。除此之外,需要靈活處理的主要包括4部分:常量池、字段表集合、方法表集合和屬性表集合。字段和方法都可以具備自己的屬性,Class本身也有相應(yīng)的屬性,因此,在解析字段表集合和方法表集合的同時(shí)也包含了屬性表的解析。

常量池占據(jù)了Class文件很大一部分的數(shù)據(jù),用于存儲(chǔ)所有的常量信息,包括數(shù)字和字符串常量、類名、接口名、字段名和方法名等。Java虛擬機(jī)規(guī)范定義了多種常量類型,每一種常量類型都有自己的結(jié)構(gòu)。常量池本身是一個(gè)表,在解析時(shí)有幾點(diǎn)需要注意。

每個(gè)常量類型都通過一個(gè)u1類型的tag來標(biāo)識(shí)。

表頭給出的常量池大小(constantPoolCount)比實(shí)際大1,例如,如果constantPoolCount等于47,那么常量池中有46項(xiàng)常量。

常量池的索引范圍從1開始,例如,如果constantPoolCount等于47,那么常量池的索引范圍為1~46。設(shè)計(jì)者將第0項(xiàng)空出來的目的是用于表達(dá)“不引用任何一個(gè)常量池項(xiàng)目”。

CONSTANT_Utf8_info型常量的結(jié)構(gòu)中包含u1類型的tag、u2類型的length和由length個(gè)u1類型組成的bytes,這length字節(jié)的連續(xù)數(shù)據(jù)是一個(gè)使用MUTF-8(Modified UTF-8)編碼的字符串。MUTF-8與UTF-8并不兼容,主要區(qū)別有兩點(diǎn):一是null字符會(huì)被編碼成2字節(jié)(0xC0和0x80);二是補(bǔ)充字符是按照UTF-16拆分為代理對(duì)分別編碼的,相關(guān)細(xì)節(jié)可以看這里(變種UTF-8)。

屬性表用于描述某些場景專有的信息,Class文件、字段表和方法表都有相應(yīng)的屬性表集合。Java虛擬機(jī)規(guī)范定義了多種屬性,ClassAnalyzer目前實(shí)現(xiàn)了對(duì)常用屬性的解析。和常量類型的數(shù)據(jù)項(xiàng)不同,屬性并沒有一個(gè)tag來標(biāo)識(shí)屬性的類型,但是每個(gè)屬性都包含有一個(gè)u2類型的attribute_name_index,attribute_name_index指向常量池中的一個(gè)CONSTANT_Utf8_info類型的常量,該常量包含著屬性的名稱。在解析屬性時(shí),ClassAnalyzer正是通過attribute_name_index指向的常量對(duì)應(yīng)的屬性名稱來得知屬性的類型。

字段表用于描述類或者接口中聲明的變量,字段包括類級(jí)變量以及實(shí)例級(jí)變量。字段表的結(jié)構(gòu)包含一個(gè)u2類型的access_flags、一個(gè)u2類型的name_index、一個(gè)u2類型的descriptor_index、一個(gè)u2類型的attributes_count和attributes_count個(gè)attribute_info類型的attributes。我們已經(jīng)介紹了屬性表的解析,attributes的解析方式與屬性表的解析方式一致。

Class的文件方法表采用了和字段表相同的存儲(chǔ)格式,只是access_flags對(duì)應(yīng)的含義有所不同。方法表包含著一個(gè)重要的屬性:Code屬性。Code屬性存儲(chǔ)了Java代碼編譯成的字節(jié)碼指令,在ClassAnalyzer中,Code對(duì)應(yīng)的Java類如下所示(僅列出了類屬性)

public class Code extends BasicAttributeInfo {
 private short maxStack;
 private short maxLocals;
 private long codeLength;
 private byte[] code;
 private short exceptionTableLength;
 private ExceptionInfo[] exceptionTable;
 private short attributesCount;
 private BasicAttributeInfo[] attributes;
 ...
 private class ExceptionInfo {
  public short startPc;
  public short endPc;
  public short handlerPc;
  public short catchType;
   ...
 }
}

在Code屬性中,codeLength和code分別用于存儲(chǔ)字節(jié)碼長度和字節(jié)碼指令,每條指令即一個(gè)字節(jié)(u1類型)。在虛擬機(jī)執(zhí)行時(shí),通過讀取code中的一個(gè)個(gè)字節(jié)碼,并將字節(jié)碼翻譯成相應(yīng)的指令。另外,雖然codeLength是一個(gè)u4類型的值,但是實(shí)際上一個(gè)方法不允許超過65535條字節(jié)碼指令。

代碼實(shí)現(xiàn)

ClassAnalyzer的源碼已放在了GitHub上。在ClassAnalyzer的README中,我以一個(gè)類的Class文件為例,對(duì)該Class文件的每個(gè)字節(jié)進(jìn)行了分析,希望對(duì)大家的理解有所幫助。

參考

深入理解Java虛擬機(jī)

結(jié)束語:以上就是本文關(guān)于如何實(shí)現(xiàn)一個(gè)Java class 解析器的全部內(nèi)容,希望對(duì)大家有所幫助。

  • ???????Java公平鎖和非公平鎖的區(qū)別

    ???????Java公平鎖和非公平鎖的區(qū)別

    本文介紹???????Java公平鎖和非公平鎖區(qū)別,公平鎖是每個(gè)線程獲取鎖順序是按照線程訪問鎖的先后順序獲取的,最前面的線程總是最先獲取到鎖;而非公平鎖是每個(gè)線程獲取鎖的順序是隨機(jī)的,并不會(huì)遵循先來先得的規(guī)則,所有線程會(huì)競爭獲取鎖,下文內(nèi)容需要的朋友可以參考下
    2022-05-05
  • SpringBoot中的@CrossOrigin注解詳解

    SpringBoot中的@CrossOrigin注解詳解

    這篇文章主要介紹了SpringBoot中的@CrossOrigin注解詳解,跨源資源共享(CORS)是由大多數(shù)瀏覽器實(shí)現(xiàn)的W3C規(guī)范,允許您靈活地指定什么樣的跨域請(qǐng)求被授權(quán),而不是使用一些不太安全和不太強(qiáng)大的策略,需要的朋友可以參考下
    2023-11-11
  • Java?超詳細(xì)講解十大排序算法面試無憂

    Java?超詳細(xì)講解十大排序算法面試無憂

    這篇文章主要介紹了Java常用的排序算法及代碼實(shí)現(xiàn),在Java開發(fā)中,對(duì)排序的應(yīng)用需要熟練的掌握,這樣才能夠確保Java學(xué)習(xí)時(shí)候能夠有扎實(shí)的基礎(chǔ)能力。那Java有哪些排序算法呢?本文小編就來詳細(xì)說說Java常見的排序算法,需要的朋友可以參考一下
    2022-04-04
  • java并發(fā)編程StampedLock高性能讀寫鎖詳解

    java并發(fā)編程StampedLock高性能讀寫鎖詳解

    這篇文章主要為大家介紹了java并發(fā)編程StampedLock高性能讀寫鎖的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • java中int初始化可以為0,但不能為NULL問題

    java中int初始化可以為0,但不能為NULL問題

    這篇文章主要介紹了java中int初始化可以為0,但不能為NULL問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • JavaWeb實(shí)現(xiàn)打印功能

    JavaWeb實(shí)現(xiàn)打印功能

    這篇文章主要介紹了JavaWeb實(shí)現(xiàn)打印功能的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-05-05
  • 詳解Java的初始化與清理

    詳解Java的初始化與清理

    這篇文章主要介紹了Java的初始化與清理,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • Java數(shù)字轉(zhuǎn)中文大寫工具類詳細(xì)代碼(拿去即用)

    Java數(shù)字轉(zhuǎn)中文大寫工具類詳細(xì)代碼(拿去即用)

    最近項(xiàng)目中用到金額轉(zhuǎn)大寫的地方,索性給大家總結(jié)下,這篇文章主要給大家介紹了關(guān)于Java數(shù)字轉(zhuǎn)中文大寫工具類的相關(guān)資料,文中給出了詳細(xì)的代碼示例,需要的朋友可以參考下
    2024-05-05
  • Java如何利用Socket進(jìn)行數(shù)據(jù)讀寫

    Java如何利用Socket進(jìn)行數(shù)據(jù)讀寫

    這篇文章主要介紹了Java如何利用Socket進(jìn)行數(shù)據(jù)讀寫,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 最新評(píng)論

    太保市| 淅川县| 海安县| 濉溪县| 鲁甸县| 且末县| 民丰县| 庆元县| 蚌埠市| 泽州县| 中西区| 扬州市| 杭州市| 山西省| 托克逊县| 苍南县| 鄂托克旗| 孝义市| 宜川县| 白水县| 湟源县| 康马县| 云霄县| 车致| 靖州| 嵩明县| 南靖县| 和硕县| 乳山市| 建湖县| 德江县| 宣化县| 界首市| 壤塘县| 女性| 吉安市| 镇巴县| 苏尼特右旗| 开封县| 岐山县| 清新县|