Class文件解析

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

整體結(jié)構(gòu)

ClassFile {
    u4             magic;
    u2             minor_version;
    u2             major_version;
    u2             constant_pool_count;
    cp_info        constant_pool[constant_pool_count-1];
    u2             access_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];
}

從結(jié)構(gòu)上看可以分為幾大塊 文件頭士鸥、常量池、接口葛躏、字段局齿、函數(shù)剧劝、屬性

文件頭

 u4             magic;  //固定值 0xCAFEBABE
 u2             minor_version;
 u2             major_version;
 u2             access_flags;  //訪問修飾
 u2             this_class; //類名 常量池下標(biāo)
 u2             super_class; //父類名 常量池下標(biāo)  如果是0 就是java/lang/Object;
</pre></code>
我把這幾個(gè)描述了類基本信息的字段稱為文件頭

major_version.minor_version表示該class文件的版本號(hào),由編譯器版本決定,然而不同版本的虛擬機(jī)只會(huì)支持一定版本范圍內(nèi)的class文件抓歼,如果不在則會(huì)拒絕解析讥此。
例如 openJDK中的實(shí)現(xiàn)
<pre><code>
// Check version numbers - we check this even with verifier off
  if (!is_supported_version(major_version, minor_version)) {
    if (name == NULL) {
      Exceptions::fthrow(
        THREAD_AND_LOCATION,
        vmSymbols::java_lang_UnsupportedClassVersionError(),
        "Unsupported major.minor version %u.%u",
        major_version,
        minor_version);
    } 

常量池

常量池包含了class文件中使用到的例如 函數(shù)標(biāo)識(shí)/類型信息/字符串等等,運(yùn)行時(shí)加載到內(nèi)存中形成運(yùn)行時(shí)常量池

常量項(xiàng)中文件中使用變長(zhǎng)結(jié)構(gòu)描述

cp_info {
    u1 tag;  //表示常量的類型
    u1 info[];  //具體常量的內(nèi)容結(jié)構(gòu) 不同類型常量有不同的結(jié)構(gòu)
}

/*常量類型*/
Constant Type   Value
CONSTANT_Class  7
CONSTANT_Fieldref   9
CONSTANT_Methodref  10
CONSTANT_InterfaceMethodref 11
CONSTANT_String 8
CONSTANT_Integer    3
CONSTANT_Float  4
CONSTANT_Long   5
CONSTANT_Double 6
CONSTANT_NameAndType    12
CONSTANT_Utf8   1
CONSTANT_MethodHandle   15
CONSTANT_MethodType 16
CONSTANT_InvokeDynamic  18

例如:Utf8_info常量,更多的可以查看規(guī)范

CONSTANT_Utf8_info {
    u1 tag;
    u2 length;  //字符串長(zhǎng)度
    u1 bytes[length]; //字符串?dāng)?shù)據(jù)(utf-8編碼)
}

解析常量池的時(shí)候要注意:常量池長(zhǎng)度為 constant_pool_count -1 但是 下標(biāo)從1開始

屬性表

attribute_info {
    u2 attribute_name_index;
    u4 attribute_length;
    u1 info[attribute_length];
}

屬性項(xiàng)可以包含在class谣妻、method萄喳、field、code中蹋半,作為具體信息項(xiàng)

在class中可以描述文件信息他巨,在method中可以描述字節(jié)碼內(nèi)容,函數(shù)棧信息减江,在code中可以描述行號(hào)等 所以attribute_info同樣是具備不同類型的變長(zhǎng)結(jié)構(gòu)染突。但是attribute_info并沒有tag這樣的專門標(biāo)記去標(biāo)識(shí)類型,而是使用名字attribute_name辈灼。

//一部分Attribute Name
Attribute   Section class file  Java SE
ConstantValue   §4.7.2  45.3    1.0.2
Code    §4.7.3  45.3    1.0.2
StackMapTable   §4.7.4  50.0    6
Exceptions  §4.7.5  45.3    1.0.2
InnerClasses    §4.7.6  45.3    1.1
//.......

Code_attribute結(jié)構(gòu)

Code_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 max_stack;  //最大棧深度
    u2 max_locals;  //局部變量數(shù)量
    u4 code_length; //字節(jié)碼內(nèi)容長(zhǎng)度
    u1 code[code_length];  //字節(jié)碼內(nèi)容
    u2 exception_table_length;  //異常處理表 由try,catch/finaly 產(chǎn)生
    {   u2 start_pc;
        u2 end_pc;
        u2 handler_pc;
        u2 catch_type;
    } exception_table[exception_table_length];
    u2 attributes_count;
    attribute_info attributes[attributes_count];
}

函數(shù)表/字段表


method_info {
    u2             access_flags;
    u2             name_index;
    u2             descriptor_index;
    u2             attributes_count;
//一定會(huì)包含一個(gè)code屬性項(xiàng)
    attribute_info attributes[attributes_count];
}

field_info {
    u2             access_flags;
    u2             name_index;
    u2             descriptor_index;
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

可以看到函數(shù)/字段中的內(nèi)容具體有屬性來描述

字節(jié)碼解析

對(duì)于class文件解析份企,我們最關(guān)心的可能就兩個(gè) 常量池和字節(jié)碼

一條字節(jié)碼由操作碼,操作數(shù)組成,不同的字節(jié)碼操作數(shù)的長(zhǎng)度/表示意義可能不一樣巡莹,對(duì)著規(guī)范翻譯就好

例如invokevirtual字節(jié)碼就是 0xb6 u2 2字節(jié)的操作數(shù)在運(yùn)行時(shí)指向的是一個(gè)instance method ref

參考文檔

  1. JVM規(guī)范-Class文件結(jié)構(gòu)

  2. JVM規(guī)范-字節(jié)碼

本文代碼

ClassParserDemo

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末司志,一起剝皮案震驚了整個(gè)濱河市甜紫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌俐芯,老刑警劉巖棵介,帶你破解...
    沈念sama閱讀 211,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異吧史,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)唠雕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門贸营,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人岩睁,你說我怎么就攤上這事钞脂。” “怎么了捕儒?”我有些...
    開封第一講書人閱讀 157,435評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵冰啃,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我刘莹,道長(zhǎng)阎毅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,509評(píng)論 1 284
  • 正文 為了忘掉前任点弯,我火速辦了婚禮扇调,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘抢肛。我一直安慰自己狼钮,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評(píng)論 6 386
  • 文/花漫 我一把揭開白布捡絮。 她就那樣靜靜地躺著熬芜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪福稳。 梳的紋絲不亂的頭發(fā)上涎拉,一...
    開封第一講書人閱讀 49,837評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音灵寺,去河邊找鬼曼库。 笑死,一個(gè)胖子當(dāng)著我的面吹牛略板,可吹牛的內(nèi)容都是我干的毁枯。 我是一名探鬼主播,決...
    沈念sama閱讀 38,987評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼叮称,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼种玛!你這毒婦竟也來了藐鹤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,730評(píng)論 0 267
  • 序言:老撾萬榮一對(duì)情侶失蹤赂韵,失蹤者是張志新(化名)和其女友劉穎娱节,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體祭示,經(jīng)...
    沈念sama閱讀 44,194評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肄满,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了质涛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稠歉。...
    茶點(diǎn)故事閱讀 38,664評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖汇陆,靈堂內(nèi)的尸體忽然破棺而出怒炸,到底是詐尸還是另有隱情,我是刑警寧澤毡代,帶...
    沈念sama閱讀 34,334評(píng)論 4 330
  • 正文 年R本政府宣布阅羹,位于F島的核電站,受9級(jí)特大地震影響教寂,放射性物質(zhì)發(fā)生泄漏捏鱼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評(píng)論 3 313
  • 文/蒙蒙 一孝宗、第九天 我趴在偏房一處隱蔽的房頂上張望穷躁。 院中可真熱鬧,春花似錦因妇、人聲如沸问潭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽狡忙。三九已至,卻和暖如春址芯,著一層夾襖步出監(jiān)牢的瞬間灾茁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工谷炸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留北专,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,389評(píng)論 2 360
  • 正文 我出身青樓旬陡,卻偏偏與公主長(zhǎng)得像拓颓,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子描孟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容