国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

如何實現(xiàn)一個Java Class字節(jié)解析器(Golang版)

diabloneo / 1206人閱讀

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

最近在寫一個私人項目,名字叫做SmallVM,SmallVM的目的在于通過實現(xiàn)一個輕量級的Java虛擬機,加深對Java虛擬機的認(rèn)知和理解。在Java虛擬機加載類的過程中,需要對Class文件進行解析,我曾經(jīng)多帶帶實現(xiàn)過一個Java版的Class字節(jié)解析器ClassAnalyzer,相比于Java版,新版(Golang版)更加健壯,思路也更加清晰。本文即闡述我實現(xiàn)Class字節(jié)解析器的思路。

Class文件

作為類或者接口信息的載體,每個Class文件都完整的定義了一個類。為了使Java程序可以“編寫一次,處處運行”,Java虛擬機規(guī)范對Class文件進行了嚴(yán)格的規(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ī)范定義了u1、u2u4u8來分別表示1個字節(jié)、2個字節(jié)、4個字節(jié)和8個字節(jié)的無符號數(shù),無符號數(shù)可以用來描述數(shù)字、索引引用、數(shù)量值或者是字符串。表是由多個無符號數(shù)或者其它表作為數(shù)據(jù)項構(gòu)成的復(fù)合數(shù)據(jù)類型,表用于描述有層次關(guān)系的復(fù)合結(jié)構(gòu)的數(shù)據(jù),因此整個Class文件本質(zhì)上就是一張表。在SmallVMu1u2、u4u8分別對應(yīng)于uint8、uint16、uint32uint64,Class文件被描述為如下結(jié)構(gòu)體。

type ClassFile struct {
    magic             uint32
    minorVersion      uint16
    majorVersion      uint16
    constantPoolCount uint16
    constantPool      []constantpool.ConstantInfo
    accessFlags       uint16
    thisClass         uint16
    superClass        uint16
    interfacesCount   uint16
    interfaces        []uint16
    fieldsCount       uint16
    fields            []FieldInfo
    methodsCount      uint16
    methods           []MethodInfo
    attributesCount   uint16
    attributes        []attribute.AttributeInfo
}

type FieldInfo struct {
    accessFlags     uint16
    nameIndex       uint16
    descriptorIndex uint16
    attributesCount uint16
    attributes      []attribute.AttributeInfo
}

type MethodInfo struct {
    accessFlags     uint16
    nameIndex       uint16
    descriptorIndex uint16
    attributesCount uint16
    attributes      []attribute.AttributeInfo
}
如何解析

組成Class文件的各個數(shù)據(jù)項中,例如魔數(shù)、Class文件的版本、訪問標(biāo)志、類索引和父類索引等數(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來標(biāo)識。

表頭給出的常量池大?。?b>constantPoolCount)比實際大1,例如,如果constantPoolCount等于47,那么常量池中有46項常量。

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

如果一個CONSTANT_Long_infoCONSTANT_Double_info結(jié)構(gòu)的項在常量池中的索引為n,則常量池中下一個有效的項的索引為n+2,此時常量池中索引為n+1的項有效但必須被認(rèn)為不可用。

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

屬性表用于描述某些場景專有的信息,Class文件、字段表和方法表都有相應(yīng)的屬性表集合。Java虛擬機規(guī)范定義了多種屬性,SmallVM目前實現(xiàn)了對常用屬性的解析。和常量類型的數(shù)據(jù)項不同,屬性并沒有一個tag來標(biāo)識屬性的類型,但是每個屬性都包含有一個u2類型的attribute_name_index,attribute_name_index指向常量池中的一個CONSTANT_Utf8_info類型的常量,該常量包含著屬性的名稱。在解析屬性時,SmallVM正是通過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é)碼指令,在SmallVM中,Code對應(yīng)的結(jié)構(gòu)體如下所示(僅列出了類屬性)。

type Code struct {
    pool                 []constantpool.ConstantInfo
    attributeNameIndex   uint16
    attributeLength      uint32
    maxStack             uint16
    maxLocals            uint16
    codeLength           uint32
    code                 []byte
    exceptionTableLength uint16
    exceptionTable       []ExceptionInfo
    attributesCount      uint16
    attributes           []AttributeInfo
}

type ExceptionInfo struct {
    startPc   uint16
    endPc     uint16
    handlerPc uint16
    catchType uint16
}

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

代碼實現(xiàn)

整個Class字節(jié)解析器的源碼已放在了GitHub上,字節(jié)解析器僅僅是SmallVM的一個小模塊,對應(yīng)的目錄為src/classfile。另外,可以參考ClassAnalyzer的README,我以一個類的Class文件為例,對該Class文件的每個字節(jié)進行了分析,希望對大家的理解有所幫助。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/66899.html

相關(guān)文章

  • Golang實現(xiàn)簡單爬蟲框架(3)——簡單并發(fā)

    摘要:在上篇文章實現(xiàn)簡單爬蟲框架單任務(wù)版爬蟲中我們實現(xiàn)了一個簡單的單任務(wù)版爬蟲,對于單任務(wù)版爬蟲,每次都要請求頁面,然后解析數(shù)據(jù),然后才能請求下一個頁面。在上篇文章Golang實現(xiàn)簡單爬蟲框架(2)——單任務(wù)版爬蟲中我們實現(xiàn)了一個簡單的單任務(wù)版爬蟲,對于單任務(wù)版爬蟲,每次都要請求頁面,然后解析數(shù)據(jù),然后才能請求下一個頁面。整個過程中,獲取網(wǎng)頁數(shù)據(jù)速度比較慢,那么我們就把獲取數(shù)據(jù)模塊做成并發(fā)執(zhí)行。在...

    番茄西紅柿 評論0 收藏0
  • Golang實現(xiàn)簡單爬蟲框架(3)——簡單并發(fā)

    摘要:在上篇文章實現(xiàn)簡單爬蟲框架單任務(wù)版爬蟲中我們實現(xiàn)了一個簡單的單任務(wù)版爬蟲,對于單任務(wù)版爬蟲,每次都要請求頁面,然后解析數(shù)據(jù),然后才能請求下一個頁面。在上篇文章Golang實現(xiàn)簡單爬蟲框架(2)——單任務(wù)版爬蟲中我們實現(xiàn)了一個簡單的單任務(wù)版爬蟲,對于單任務(wù)版爬蟲,每次都要請求頁面,然后解析數(shù)據(jù),然后才能請求下一個頁面。整個過程中,獲取網(wǎng)頁數(shù)據(jù)速度比較慢,那么我們就把獲取數(shù)據(jù)模塊做成并發(fā)執(zhí)行。在...

    lewinlee 評論0 收藏0
  • 關(guān)于ClassLoader的學(xué)習(xí)筆記,詳解

    摘要:它負(fù)責(zé)將的字節(jié)碼形式轉(zhuǎn)換成內(nèi)存形式的對象。先使用工具對字節(jié)碼文件進行加密,運行時使用定制的先解密文件內(nèi)容再加載這些解密后的字節(jié)碼。的方法是需要子類來覆蓋的,不同的加載器將使用不同的邏輯來獲取目標(biāo)類的字節(jié)碼。 ClassLoader 詳解 ClassLoader 做什么的? 延遲加載 各司其職 ClassLoader 傳遞性 雙親委派 Class.forName 自定義加載器 Clas...

    zgbgx 評論0 收藏0
  • JVM類加載思維導(dǎo)圖

    摘要:用一張思維導(dǎo)圖盡可能囊括一下的類加載過程的全流程。本文參考自來自周志明深入理解虛擬機第版,拓展內(nèi)容建議讀者可以閱讀下這本書。 用一張思維導(dǎo)圖盡可能囊括一下JVM的類加載過程的全流程。 本文參考自來自周志明《深入理解Java虛擬機(第2版)》,拓展內(nèi)容建議讀者可以閱讀下這本書。 showImg(http://ocxhn1mzz.bkt.clouddn.com/class%20loadin...

    Crazy_Coder 評論0 收藏0
  • JavaWEB開發(fā)18——基礎(chǔ)加強

    摘要:一類加載器什么是類加載器,作用是什么類加載器就加載字節(jié)碼文件類加載器的種類類加載器有三種,不同類加載器加載不同的引導(dǎo)類加載器加載都是最基礎(chǔ)的文件擴展類加載器加載都是基礎(chǔ)的文件應(yīng)用類加載器三方包和自己編寫文件怎么獲得類加載器重點字節(jié)碼對象二注 一、類加載器1.什么是類加載器,作用是什么?類加載器就加載字節(jié)碼文件(.class) 2.類加載器的種類類加載器有三種,不同類加載器加載不同的 1...

    Youngdze 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<