上面的內容是來自《The Java Virtual Machine Specification,Second Edition》的4.1節“The ClassFile Structure"。
之前反匯編的UserService.class文件反匯編的結果的前16個字節在十六進制編輯器中如下所示:
ca fe ba be 00 00 00 32 00 28 07 00 02 01 00 1b
通過這些數值,我們可以來看看class文件的格式。
magic:class文件最開始的四個字節是魔數。它的值是用來標識Java class文件的。從上面的內容里可以看出,魔數 的值是0xCAFEBABE。簡而言之,只有一個文件的起始4字節是0xCAFEBABE的時候,它才會被當作Java class文件來處理。
minor_version,major_version:接下來的四個字節表示的是class文件的版本。UserService.class文件里的是0x00000032,所以這個class文件的版本是50.0。JDK 1.6編譯的class文件的版本是50.0,JDK 1.5編譯出來的class文件的版本是49.0。JVM必須對低版本的class文件保持后向兼容性,也就是低版本的class文件可以運行在高版本的JVM上。不過,反過來就不行了,當一個高版本的class文件運行在低版本的JVM上時,會出現java.lang.UnsupportedClassVersionError的錯誤。
constant_pool_count,constant_pool[]:在版本號之后,存放的是類的常量池。這里保存的信息將會放入運行時常量池(Runtime Constant Pool)中去,這個后面會講解的。在加載一個class文件的時候,JVM會把常量池里的信息存放在方法區的運行時常量區里。UserService.class文件里的constant_pool_count的值是0x0028,這表示常量池里有39(40-1)個常量。
access_flags:這是表示一個類的描述符的標志;換句話說,它表示一個類是public,final還是abstract以及是不是接口的標志。
fields_count,fields[]:當前類的成員變量的數量以及成員變量的信息。成員變量的信息包含變量名,類型,修飾符以及變量在constant_pool里的索引。
methods_count,methods[]:當前類的方法數量以及方法的信息。方法的信息包含方法名,參數的數量和類型,返回值的類型,修飾符,以及方法在constant_pool里的索引,方法的可執行代碼以及異常信息。
attributes_count,attributes[]:attribution_info結構包含不同種類的屬性。field_info和method_info里都包含了attribute_info結構。
javap簡要地給出了class文件的一個可讀形式。當你用"java -verbose"命令來分析UserService.class時,會輸出如下的內容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
Compiled from "UserService.java" public class com.nhn.service.UserService extends java.lang.Object SourceFile: "UserService.java" minor version: 0 major version: 50 Constant pool: const # 1 = class # 2 ; // com/nhn/service/UserService const # 2 = Asciz com/nhn/service/UserService; const # 3 = class # 4 ; // java/lang/Object const # 4 = Asciz java/lang/Object; const # 5 = Asciz admin; const # 6 = Asciz Lcom/nhn/user/UserAdmin;; // … omitted - constant pool continued … { // … omitted - method information … public void add(java.lang.String); Code: Stack= 2 , Locals= 2 , Args_size= 2 0 : aload_0 1 : getfield # 15 ; //Field admin:Lcom/nhn/user/UserAdmin; 4 : aload_1 5 : invokevirtual # 23 ; //Method com/nhn/user/UserAdmin.addUser:(Ljava/lang/String;)Lcom/nhn/user/User; 8 : pop 9 : return LineNumberTable: line 14 : 0 line 15 : 9 LocalVariableTable: Start Length Slot Name Signature 0 10 0 this Lcom/nhn/service/UserService; 0 10 1 userName Ljava/lang/String; // … Omitted - Other method information … } |
原文轉自:http://www.anti-gravitydesign.com