文章詳情頁
剖析java的class文件結(jié)構(gòu)
瀏覽:68日期:2024-07-02 14:24:50
內(nèi)容: 定義:u1 1個(gè)字節(jié)為單位的非負(fù)值 u2 2個(gè)字節(jié)為單位的非負(fù)值 u3 . . . . . . . . (其他以此類推 ) Java文件結(jié)構(gòu)用類似struct的描述如下: ClassFile { u4 magic; // 必須為: 0xCAFEBABE u2 minor_version; u2 major_version; //CLASS文件結(jié)構(gòu)主次版本號 JAVA2支持45.0-46.0 u2 constant_pool_count; //記錄常量信息 cp_info constant_pool[constant_pool_count-1]; //計(jì)數(shù)從1開始 u2 access_flags; //class/interface訪問權(quán)限 u2 this_class; //指向constant_poll中的有效索引值 u2 super_class; //0或指向constant_poll中的有效索引值,對于interface必須為非0 u2 interfaces_count; //superinterfaces的個(gè)數(shù) u2 interfaces[interfaces_count]; //計(jì)數(shù)[0,count-1) 對應(yīng)constant_pool中的一個(gè)索引值 u2 fields_count; field_info fields[fields_count]; //主要用于記錄class及實(shí)例中的變量 u2 methods_count; method_info methods[methods_count]; u2 attributes_count; attribute_info attributes[attributes_count]; } cp_info { u1 tag; u1 info[]; }tag 意義如下: 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 此時(shí)cp_info分別對應(yīng)結(jié)構(gòu)變化為 1. CONSTANT_Class CONSTANT_Class_info { u1 tag; u2 name_index; } 2. CONSTANT_Fieldref CONSTANT_Fieldref_info { u1 tag; u2 class_index; //constant_pool的索引,對應(yīng)CONSTANT_Class_info u2 name_and_type_index;//constant_pool的索引,對應(yīng)CONSTANT_NameAndType_info } 3. CONSTANT_Methodref CONSTANT_Methodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } 4. CONSTANT_InterfaceMethodref CONSTANT_InterfaceMethodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } 5. CONSTANT_String CONSTANT_String_info { u1 tag; u2 string_index; } 6. CONSTANT_Integer CONSTANT_Integer_info { u1 tag; u4 bytes; } 7. CONSTANT_Float CONSTANT_Float_info { u1 tag; u4 bytes; } 8. CONSTANT_Long CONSTANT_Long_info { u1 tag; u4 high_bytes; u4 low_bytes; } 9. CONSTANT_Double CONSTANT_Double_info { u1 tag; u4 high_bytes; u4 low_bytes } 10.CONSTANT_NameAndType CONSTANT_NameAndType_info { u1 tag; u2 name_index; u2 descriptor_index; } 11.CONSTANT_Utf8 CONSTANT_Utf8_info { u1 tag; u2 length; u1 bytes[length]; } access_flags意義如下: ACC_PUBLIC 0x0001 ACC_FINAL 0x0010 ACC_SUPER 0x0020 ACC_INTERFACE 0x0200 ACC_ABSTRACT 0x0400 如果是interface那么必須置ACC_INTERFACE,如果沒有置ACC_INTERFACE則定義的是一個(gè)類而非接口。 如果設(shè)置了ACC_INTERFACE,那么ACC_ABSTRACT位也必須被設(shè)置,當(dāng)然也可以設(shè)置ACC_PUBLIC。 ACC_SUPER用以表明invokespecial語義,Sun公司老的JAVA編譯器沒有設(shè)置ACC_SUPER,并且老的JVM 忽略ACC_SUPER位,但新的編譯器應(yīng)該實(shí)現(xiàn)invokespecial語義。 其他未指明的位保留將來使用,并且編譯器應(yīng)當(dāng)將其置為0,同時(shí)Java虛擬機(jī)應(yīng)當(dāng)忽略他們。 this_class: constant_pool中的索引值,指向的元素的cp_info等價(jià)為CONSTANT_Class_info CONSTANT_Class_info { u1 tag; //必須為CONSTANT_Class (7) u2 name_index; //為指向constant_pool中的一個(gè)索引值 } name_index :指向的元素的cp_info等價(jià)為CONSTANT_Utf8_info CONSTANT_Utf8_info { u1 tag; //必須為CONSTANT_Utf8 (1) u2 length; u1 bytes[length]; //Utf8編碼的字符串 } field_info { u2 access_flags; //訪問控制權(quán) u2 name_index; //constant_pool中的索引,對應(yīng)于CONSTANT_Utf8_info描述。 u2 descriptor_index; //constant_pool中的索引,對應(yīng)于CONSTANT_Utf8_info描述。 u2 attributes_count; attribute_info attributes[attributes_count]; //attribute_info將在mothods后描述。 } field_info中access_flages意義如下: ACC_PUBLIC 0x0001 ACC_PRIVATE 0x0002 ACC_PROTECTED 0x0004 ACC_STATIC 0x0008 ACC_FINAL 0x0010 ACC_VOLATILE 0x0040 ACC_TRANSIENT 0x0080 其中很顯然不能同時(shí)為ACC_FINAL和ACC_VOLATILE ;且前三項(xiàng)是互斥的。 interface必須置ACC_PUBLIC, ACC_STATIC,ACC_FINAL位,且不能置其他位。 其他未指明的位保留將來使用,并且編譯器應(yīng)當(dāng)將其置為0,同時(shí)Java虛擬機(jī)應(yīng)當(dāng)忽略他們。 methods指明了類中的所有方法。 method_info { u2 access_flags; u2 name_index; //指向constant_pool的入口,對應(yīng)為CONSTANT_Utf8_info u2 descriptor_index; //指向constant_pool的入口,對應(yīng)為CONSTANT_Utf8_info u2 attributes_count; attribute_info attributes[attributes_count]; //此處只能出現(xiàn)Code、Exceptions、Synthetic、Deprecated四種類型的屬性 } access_flags訪問權(quán)描述如下: ACC_PUBLIC 0x0001 ACC_PRIVATE 0x0002 ACC_PROTECTED 0x0004 ACC_STATIC 0x0008 ACC_FINAL 0x0010 ACC_SYNCHRONIZED 0x0020 ACC_NATIVE 0x0100 ACC_ABSTRACT 0x0400 ACC_STRICT 0x0800 attribute_info { u2 attribute_name_index; //constant_pool中的索引,對應(yīng)于CONSTANT_Utf8_info描述。 u4 attribute_length; u1 info[attribute_length]; } 現(xiàn)在已經(jīng)預(yù)定義的屬性有: 1. SourceFile : attribute_info被替代為: SourceFile_attribute { u2 attribute_name_index; u4 attribute_length; u2 sourcefile_index; //指向constant_pool中的一個(gè)CONSTANT_Utf8_info 結(jié)構(gòu)。 } 2. ConstantValue : attribute_info被替代為: ConstantValue_attribute { u2 attribute_name_index; u4 attribute_length; //必須為2 u2 constantvalue_index; } 對于constantvalue_index意義如下: longCONSTANT_Long floatCONSTANT_Float double CONSTANT_Double int, short, char, byte, boolean CONSTANT_Integer String CONSTANT_String ConstantValue用于field_info 中,用于描述一個(gè)static常量, 且此時(shí)field_info的access_flags應(yīng)為ACC_STATIC 3. Code : attribute_info被替代為: Code_attribute { u2 attribute_name_index; u4 attribute_length; u2 max_stack; //執(zhí)行此函數(shù)時(shí)可用的棧的最大深度 u2 max_locals; //執(zhí)行此函數(shù)可用到的最大本地變量數(shù)目,包括參數(shù)。 // 注意:一個(gè)long/double相當(dāng)于2個(gè)變量數(shù)目. u4 code_length; //本函數(shù)用到的代碼長度。 u1 code[code_length]; //實(shí)現(xiàn)本函數(shù)的真正字節(jié)碼 u2 exception_table_length; { u2 start_pc; u2 end_pc; //捕獲違例時(shí)執(zhí)行代碼數(shù)組中的[start_pc, end_pc)部分 u2 handler_pc; //現(xiàn)在還不大明白他是干嘛的!! u2 catch_type; //指向constant_pool的索引,對應(yīng)CONSTANT_Class_info }exception_table[exception_table_length]; u2 attributes_count; attribute_info attributes[attributes_count]; } CONSTANT_Class_info { u1 tag; //必須為CONSTANT_Class (7) u2 name_index; //不用我再說了吧? } Code屬性用于method_info結(jié)構(gòu)中。 4. Exceptions : attribute_info被替代為: Exceptions_attribute { u2 attribute_name_index; u4 attribute_length; u2 number_of_exceptions; u2 exception_index_table[number_of_exceptions]; } 5. InnerClasses : attribute_info被替代為: InnerClasses_attribute { u2 attribute_name_index; u4 attribute_length; u2 number_of_classes; { u2 inner_class_info_index; u2 outer_class_info_index; u2 inner_name_index; u2 inner_class_access_flags; } classes[number_of_classes]; } 6. Synthetic : attribute_info被替代為: Synthetic_attribute { u2 attribute_name_index; //不用廢話了吧? u4 attribute_length; //必須為0 } Synthetic用在 field_info、 method_info 中, 一個(gè)沒有出現(xiàn)在源程序中的變量必須使用Synthetic標(biāo)記。 7. LineNumberTable : attribute_info被替代為: LineNumberTable_attribute { u2 attribute_name_index; u4 attribute_length; u2 line_number_table_length; { u2 start_pc; //代碼數(shù)組中的開始處 u2 line_number; //源文件中的行號(對于每一非空行都有這么一項(xiàng)) } line_number_table[line_number_table_length]; } LineNumberTable用于Code屬性中,通常用于調(diào)試。 8. LocalVariableTable : attribute_info被替代為: LocalVariableTable_attribute { u2 attribute_name_index; u4 attribute_length; u2 local_variable_table_length; { u2 start_pc; u2 length; //當(dāng)解釋到代碼數(shù)組的[start_pc,start_pc+length] //時(shí)變量必須被賦值?? u2 name_index; u2 descriptor_index; u2 index; //到本地變量數(shù)組的一個(gè)索引 } local_variable_table[local_variable_table_length]; } 9. Deprecated : attribute_info被替代為: Deprecated_attribute { u2 attribute_name_index; u4 attribute_length; //必須為0 } 當(dāng)然你也可以定義自己的屬性,但要你自己的編譯器和虛擬機(jī)實(shí)現(xiàn)。JVM將忽略自己不認(rèn)可的屬性。來實(shí)踐一下吧!編寫一個(gè)最簡單的程序:class Test { public static void main(String[] args) { System.out.println('Hello World!'); }}c:work>javac Test.javac:work>filedump Test.classFile Dump V0.3 Beta by cloud ([email protected]).01:00 ca fe ba be 00 03 00 2d 00 1d 0a 00 06 00 0f 09 .......-........01:01 00 10 00 11 08 00 12 0a 00 13 00 14 07 00 15 07 ................01:02 00 16 01 00 06 3c 69 6e 69 74 3e 01 00 03 28 29 ........()01:03 56 01 00 04 43 6f 64 65 01 00 0f 4c 69 6e 65 4e V...Code...LineN01:04 75 6d 62 65 72 54 61 62 6c 65 01 00 04 6d 61 69 umberTable...mai01:05 6e 01 00 16 28 5b 4c 6a 61 76 61 2f 6c 61 6e 67 n...([Ljava/lang01:06 2f 53 74 72 69 6e 67 3b 29 56 01 00 0a 53 6f 75 /String;)V...Sou01:07 72 63 65 46 69 6c 65 01 00 09 54 65 73 74 2e 6a rceFile...Test.j>d02:00 61 76 61 0c 00 07 00 08 07 00 17 0c 00 18 00 19 ava.............02:01 01 00 0c 48 65 6c 6c 6f 20 57 6f 72 6c 64 21 07 ...Hello World!.02:02 00 1a 0c 00 1b 00 1c 01 00 04 54 65 73 74 01 00 ..........Test..02:03 10 6a 61 76 61 2f 6c 61 6e 67 2f 4f 62 6a 65 63 .java/lang/Objec02:04 74 01 00 10 6a 61 76 61 2f 6c 61 6e 67 2f 53 79 t...java/lang/Sy02:05 73 74 65 6d 01 00 03 6f 75 74 01 00 15 4c 6a 61 stem...out...Lja02:06 76 61 2f 69 6f 2f 50 72 69 6e 74 53 74 72 65 61 va/io/PrintStrea02:07 6d 3b 01 00 13 6a 61 76 61 2f 69 6f 2f 50 72 69 m;...java/io/Pri>d03:00 6e 74 53 74 72 65 61 6d 01 00 07 70 72 69 6e 74 ntStream...print03:01 6c 6e 01 00 15 28 4c 6a 61 76 61 2f 6c 61 6e 67 ln...(Ljava/lang03:02 2f 53 74 72 69 6e 67 3b 29 56 00 20 00 05 00 06 /String;)V. ....03:03 00 00 00 00 00 02 00 00 00 07 00 08 00 01 00 09 ................03:04 00 00 00 1d 00 01 00 01 00 00 00 05 2a b7 00 01 ............*...03:05 b1 00 00 00 01 00 0a 00 00 00 06 00 01 00 00 00 ................03:06 01 00 09 00 0b 00 0c 00 01 00 09 00 00 00 25 00 ..............%.03:07 02 00 01 00 00 00 09 b2 00 02 12 03 b6 00 04 b1 ................>d04:00 00 00 00 01 00 0a 00 00 00 0a 00 02 00 00 00 05 ................04:01 00 08 00 06 00 01 00 0d 00 00 00 02 00 0e ..............>解讀一下:ca fe ba be magic00 03 00 2d 次主版本號,換算一下: 45.3 (注意,不是高字節(jié)在前,別犯職業(yè)病!)00 1d constant_pool元素個(gè)數(shù)加一 : 29 那么constant_pool就是[1-28]constant_pool: 1-281. 0a 00 06 00 0f 0x0a :CONSTANT_InterfaceMethodref 0x06 :class index 0x0f :name-type-index2. 09 00 10 00 11 0x09 : CONSTANT_Fieldref 0x10: . . . 0x11 : . . . .3. 08 00 12 0x08 : CONSTANT_String 0x12 : string_index4. 0a 00 13 00 14 0x0a同于1.5. 07 00 15 0x07 : CONSTANT_Class 0x15 : name_index6. 07 00 16 7. 01 00 06 3c 69 6e 69 74 3e 01 ... 0x01 CONSTANT_Utf8 0x06 : string length '' : 構(gòu)造函數(shù)8. 01 00 03 28 29 56 ...()V 函數(shù),無參數(shù) 0x01 . . . . . . 0x03 : . . . . '()V' : . . .9. 01 00 04 43 6f 64 65 ...Code10. 01 00 0f 4c 69 6e 65 4e 75 6d 62 65 72 54 61 62 6c 65 ...LineNumberTable11. 01 00 04 6d 61 69 6e ...main12. 01 00 16 28 5b 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72 69 6e 67 3b 29 56 ...([Ljava/lang/String;)V 函數(shù),參數(shù)為String[]類型13. 01 00 0a 53 6f 75 72 63 65 46 69 6c 65 ...SourceFile14. 01 00 09 54 65 73 74 2e 6a 61 76 61 ...Test.java15. 0c 00 07 00 08 0x0c:CONSTANT_NameAndType 07 : name-index 08:name-type-index16. 07 00 1717. 0c 00 18 00 1918. 01 00 0c 48 65 6c 6c 6f 20 57 6f 72 6c 64 21 ...Hello World!19. 07 00 1a20. 0c 00 1b 00 1c21. 01 00 04 54 65 73 74 ...Test22. 01 00 10 6a 61 76 61 2f 6c 61 6e 67 2f 4f 62 6a 65 63 74 ...java/lang/Object23. 01 00 10 6a 61 76 61 2f 6c 61 6e 67 2f 53 79 73 74 65 6d ...java/lang/System24. 01 00 03 6f 75 74 ...out25. 01 00 15 4c 6a 61 76 61 2f 69 6f 2f 50 72 69 6e 74 53 74 72 65 61 6d 3b ...Ljava/io/PrintStream;26. 01 00 13 6a 61 76 61 2f 69 6f 2f 50 72 69 6e 74 53 74 72 65 61 6d...java/io/PrintStream27. 01 00 07 70 72 69 6e 74 6c 6e ...println28. 01 00 15 28 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72 69 6e 67 3b 29 56 ...(Ljava/lang/String;)V00 20 access_flags 00 05 this_class00 06 super_class00 00 interfaces_count00 00 fields_count00 02 methods_countmethods[2]:method_info { u2 access_flags; u2 name_index; u2 descriptor_index; u2 attributes_count; attribute_info attributes[attributes_count];}0. 00 00 access_flags; 00 07 name_index; 看看constant_pool的第7項(xiàng): 表明當(dāng)前描述構(gòu)造函數(shù) 00 08 descriptor_index; 00 01 attributes_count; 00 09 attribute_name_index 0x09 看看constant_pool的第9項(xiàng),簡單明了Code ?。? 00 00 00 1d attribute_length = 29 00 01 max_stack 00 01 max_locals 00 00 00 05 code_length 2a b7 00 01 b1 JVM定義的操作碼代碼段數(shù)組 00 00 exception_table_length 00 01 attributes_count 一個(gè),接下來是attribute_info結(jié)構(gòu) 00 0a attribute_name_index 看看constant_pool的第10項(xiàng): LineNumberTable(顯然調(diào)試用) 00 00 00 06 attribute_length 00 01 line_number_table_length 00 00 start_pc 00 01 line_number1. 00 09 access_flags PUBLIC & STATIC 00 0b name_index; 表明當(dāng)前描述main函數(shù) 00 0c descriptor_index; ...([Ljava/lang/String;)V 00 01 attributes_count; 00 09 attribute_name_index Code 00 00 00 25 attribute_length = 37 00 02 max_stack 00 01 max_locals 00 00 00 09 code_length b2 00 02 12 03 b6 00 04 b1 代碼數(shù)組 codeArray1[0-8] 00 00 exception_table_length 00 01 attributes_count 接下來是attribute_info結(jié)構(gòu) 00 0a attribute_name_index LineNumberTable 00 00 00 0a attribute_length 00 02 line_number_table_length 00 00 start_pc 00 05 line_number 00 08 start_pc : codeArray1[8] = 0xb1 return 00 06 line_number 第6行源程序?yàn)?} 00 01 attributes_count00 0d attribute_name_index 屬性為SourceFile00 00 00 02 attribute_length00 0e sourcefile_index constant_pool[0x0e] ---> 'Test.java'接下來我們看看main()函數(shù)對應(yīng)的代碼:b2 00 02 12 03 b6 00 04 b10xb2 0x00 0x02 : getstatic #2 看看constant_pool[0x02] :09 00 10 00 11 0x09 : CONSTANT_Fieldref 0x10: class index 0x11 :name-type-index constant_pool[0x10]: constant_pool[0x17] : java/lang/System constant_pool[0x11]: 0x18 : class index 0x19 :name-type-index constant_pool[0x18] : out constant_pool[0x19] : Ljava/io/PrintStream 即 System.out 為 java.io.PrintStream 類型 0x12 0x03 : ldc #3 看看 constant_pool[3] : 08 00 12 0x08 : CONSTANT_String 0x12 : string_index 指向一個(gè)字符串 constant_pool[0x12]: 'Hello World!' 故該指令加載了字符串索引到本地棧0xb6 0x00 0x04: invokevirtual #4 -----到constant_pool查查 0x13 :class 0x14 :name-type 看看constant_pool[0x13]:java/io/PrintStream constant_pool[20] : 00 1b 00 1c constant_pool[0x1b]:println . . . . :(Ljava/lang/String;)V 故該指令調(diào)用了 java.io.PrintStream.println(java.lang.String) 而參數(shù)則為 ldc #3 加載的 'Hello World!'0xb1 : return關(guān)于opcode的更多信息參見 http://mrl.nyu.edu/~meyer/jvmref/ 和JVM文檔轉(zhuǎn)自 http://watercloud.nease.net/ Java, java, J2SE, j2se, J2EE, j2ee, J2ME, j2me, ejb, ejb3, JBOSS, jboss, spring, hibernate, jdo, struts, webwork, ajax, AJAX, mysql, MySQL, Oracle, Weblogic, Websphere, scjp, scjd
標(biāo)簽:
Java
相關(guān)文章:
1. Python中讀取文件名中的數(shù)字的實(shí)例詳解2. PHP安全之文件系統(tǒng)安全——Null字符問題3. Python基于requests實(shí)現(xiàn)模擬上傳文件4. Python 轉(zhuǎn)移文件至云對象存儲的方法5. PHP結(jié)構(gòu)型模式之代理模式6. Python實(shí)現(xiàn)批量壓縮文件/文件夾zipfile的使用7. python 批量重命名移動(dòng)文件8. JS樹形結(jié)構(gòu)根據(jù)id獲取父級節(jié)點(diǎn)元素的示例代碼9. 4種非常實(shí)用的python內(nèi)置數(shù)據(jù)結(jié)構(gòu)10. 使用Python文件讀寫,自定義分隔符(custom delimiter)
排行榜
