自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

自己動手實現(xiàn)一個Java Class解析器

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

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

[[183173]]

Class文件

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

根據(jù)Java虛擬機規(guī)范,Class文件采用一種類似于C語言結(jié)構(gòu)體的偽結(jié)構(gòu)來存儲數(shù)據(jù),這種偽結(jié)構(gòu)中只有兩種數(shù)據(jù)類型:無符號數(shù)和表。Java虛擬機規(guī)范定義了u1u2、u4u8來分別表示1個字節(jié)、2個字節(jié)、4個字節(jié)和8個字節(jié)的無符號數(shù),無符號數(shù)可以用來描述數(shù)字、索引引用、數(shù)量值或者是字符串。表是由多個無符號數(shù)或者其它表作為數(shù)據(jù)項構(gòu)成的符合數(shù)據(jù)類型,表用于描述有層次關(guān)系的符合結(jié)構(gòu)的數(shù)據(jù),因此整個Class文件本質(zhì)上就是一張表。在ClassAnalyzeru1、u2、u4u8分別對應(yīng)于byte、short、intlong,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文件的各個數(shù)據(jù)項中,例如魔數(shù)、Class文件的版本等數(shù)據(jù)項、訪問標志、類索引、父類索引,它們在每個Class文件中都占用固定數(shù)量的字節(jié),在解析時只需要讀取相應(yīng)數(shù)量的字節(jié)。除此之外,需要靈活處理的主要包括4部分:常量池、字段表集合、方法表集合和屬性表集合。字段和方法都可以具備自己的屬性,Class本身也有相應(yīng)的屬性,因此,在解析字段表集合和方法表集合的同時也包含了屬性表的解析。

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

  • 每個常量類型都通過一個u1類型的tag來標識。
  • 表頭給出的常量池大?。?code>constantPoolCount)比實際大1,例如,如果constantPoolCount等于47,那么常量池中有46項常量。
  • 常量池的索引范圍從1開始,例如,如果constantPoolCount等于47,那么常量池的索引范圍為1~46。設(shè)計者將第0項空出來的目的是用于表達“不引用任何一個常量池項目”。
  • CONSTANT_Utf8_info型常量的結(jié)構(gòu)中包含u1類型的tagu2類型的length和由lengthu1類型組成的bytes,這length字節(jié)的連續(xù)數(shù)據(jù)是一個使用MUTF-8Modified UTF-8)編碼的字符串。MUTF-8UTF-8并不兼容,主要區(qū)別有兩點:一是null字符會被編碼成2字節(jié)(0xC00x80);二是補充字符是按照UTF-16拆分為代理對分別編碼的,相關(guān)細節(jié)可以看這里(變種UTF-8)。

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

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

Class的文件方法表采用了和字段表相同的存儲格式,只是access_flags對應(yīng)的含義有所不同。方法表包含著一個重要的屬性:Code屬性。Code屬性存儲了Java代碼編譯成的字節(jié)碼指令,在ClassAnalyzer中,Code對應(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屬性中,codeLengthcode分別用于存儲字節(jié)碼長度和字節(jié)碼指令,每條指令即一個字節(jié)(u1類型)。在虛擬機執(zhí)行時,通過讀取code中的一個個字節(jié)碼,并將字節(jié)碼翻譯成相應(yīng)的指令。另外,雖然codeLength是一個u4類型的值,但是實際上一個方法不允許超過65535條字節(jié)碼指令。

代碼實現(xiàn)

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

責任編輯:張燕妮 來源: tinylcy
相關(guān)推薦

2023-12-30 13:33:36

Python解析器JSON

2022-10-20 11:00:52

SQL解析器

2024-12-06 09:58:09

2022-06-28 08:17:10

JSON性能反射

2019-07-05 08:39:39

GoSQL解析器

2017-03-02 13:31:02

監(jiān)控系統(tǒng)

2023-07-25 14:24:33

元素JSX解析器

2014-05-15 09:45:58

Python解析器

2024-03-08 12:45:00

C#Web服務(wù)器

2022-01-04 11:08:02

實現(xiàn)Localcache存儲

2011-11-28 15:40:52

wiresharkRDP解析器

2015-02-10 14:32:37

XSS漏洞XSS

2021-12-08 07:31:40

設(shè)計Localcache緩存

2015-06-02 10:24:43

iOS網(wǎng)絡(luò)請求降低耦合

2015-06-02 09:51:40

iOS網(wǎng)絡(luò)請求封裝接口

2020-12-02 10:13:45

JacksonJDK解析器

2023-10-10 13:28:44

Pythonpygame

2020-03-31 20:23:46

C語言TCP服務(wù)器

2021-04-26 07:31:22

SpringMVCweb框架

2023-12-16 13:21:00

Python元類ORM
點贊
收藏

51CTO技術(shù)棧公眾號