Java類文件

一、什麼是Java類文件

  Java類文件是Java程序的二進制表示形式。每一個類文件代表一個類或者接口。不可能在一個類文件中放入多個類或者接口。這樣就使得無論類文件是在哪一種平臺上生成,都可以在任何主機上執行。

  雖然類文件是Java體系結構的一部分,但是他並不是與Java語言不可分的。你可以將其他語言的程序編譯爲類文件,也可以將Java程序文件編譯爲其他二進制形式。

  Java類文件是一個基於8-bit字節的二進制流。數據塊順序的、無分割符的、big-endian的形式存儲

  二、類文件的內容

  Java的類文件中包含了所有Java虛擬機所需要的關於類和接口的信息。所有類文件中的信息都以以下的四種基本類型的存儲:

  Table 6-1. Class file "primitive types"

  u1 a single unsigned byte

  u2 two unsigned bytes

  u4 four unsigned bytes

  u8 eight unsigned bytes

  類文件中的主要部分以表6-2的順序存儲:

  Table 6-2. Format of a ClassFile Table

  Type& #9;Name Count

  u4 magic 1

  u2 minor_version 1

  u2 major_version 1

  u2 constant_pool_count 1

  cp_info constant_pool constant_pool_count-1

  u2 access_flags 1

  u2 this_class 1

  u2 super_class 1

  u2 interfaces_count 1

  u2 interfaces interfaces_count

  u2 fields_count 1

  field_info fields fields_count

  u2 methods_count 1

  method_info methods methods_count

  u2 attributes_count 1

  attribute_info attributes attributes_count

  1、魔術編碼(magic)

  每一個Java類文件的開頭四個字節都是魔術編碼(OxCAFEBABE)。通過魔術編碼可以很容易識別類文件。

  2、副版本號和主版本號(minor_version and major_version)

  剩下的四個字節是副版本號和主版本號。但Java技術在進化時,一些新的特性可能會被加入到類文件中。每一次類文件格式的變化,都會相應的改變版本號。虛 擬機通過版本號來識別自己能夠處理的類文件。Java虛擬機往往只能處理一個給定的主版本號和其下的一些副版本號。虛擬機必須拒絕那些不再處理範圍內的類 文件。

  3、常量個數和常量池(constant_pool_count and constant_pool)

  接下來的就是常量池,常量池中包含了哪些被類或者接口訪問過的常量,比如:字符串,常量(final variable values),類名,方法名。常量池作爲一個列表存儲。列表中常量的個數就是之前保存的“constant_pool_count”。

  很多常量池中的常量都引用了常量池中的其他常量,那些引用常量池常量的引用最終也會轉換爲對常量池中常量的直接引用。雖然常量列表中的索引是從1開始的,但是常量個數還是包含了0,比如一個常量列表中有15個常量,那麼它的常量個數就爲16。

  每一個常量開頭都會有一個標誌,以表示他的類型。當虛擬機讀取這個標誌時,就會知道這個常量的具體類型了。表6-3列舉了這些標誌:

  Table 6-3. Constant pool tags

  Entry Type Tag Value Description

  CONSTANT_Utf8 1 A UTF-8 encoded Unicode string

  CONSTANT_Integer 3 An int literal value

  CONSTANT_Float 4 A float literal value

  CONSTANT_Long 5 A long literal value

  CONSTANT_Double 6 A double literal value

  CONSTANT_Class 7 A symbolic reference to a class or interface

  CONSTANT_String 8 A String literal value

  CONSTANT_Fieldref 9 A symbolic reference to a field

  CONSTANT_Methodref 10 A symbolic reference to a method declared in a class

  CONSTANT_InterfaceMethodref 11 A symbolic reference to a method declared in an interface

  CONSTANT_NameAndType 12 Part of a symbolic reference to a field or method

  表6-3中的每一個標誌都會有一個相應的表格,用來描述這個標誌的所表示的一些詳細信息,這些對應的標誌都會以標誌名+_INFO來結尾。比如CONSTANT_CLASS標誌對應的就是CONSTANT_CLASS_INFO。

  常量池在程序的動態鏈接中扮演了很重要的角色。除了上邊所說的各種常量值以外,常量池中包含了一下三種符號引用:類和接口的全名,字段名和描述符,方法名 和描述符。一個字段是一個類或者接口中的實例或者類變量,字段描述符是字段的類型。方法的描述符是方法和返回值和參數的個數、順序和類型。在虛擬機將這個 類或者接口鏈接到其他類或者接口時用到這些全名。因爲類文件不包含任何關於內存結構的信息,所以這個鏈接只能以符號引用的形式存在。虛擬機在執行時將這些 符號引用轉換爲實際的地址。具體的信息參見第八章“The Linking Model”。

  4、訪問標誌(access_flags)

  緊接在常量池後面的兩個字節就是訪問標誌,表示這個類或者接口的幾方面信息,他有如下幾種值:

  Table 6-4. Flag bits in the access_flags item of ClassFile tables

  Flag Name Value Meaning if Set Set By

  ACC_PUBLIC 0x0001 Type is public Classes and interfaces

  ACC_FINAL 0x0010 Class is final Classes only

  ACC_SUPER 0x0020 Use new invokespecial semanticsClasses and interfaces

  ACC_INTERFACE 0x0200 Type is an interface, not a class All interfaces, no classes

  ACC_ABSTRACT 0x0400 Type is abstract All interfaces, some classes

  ACC_SUPER標誌是爲了兼容以前SUN的老式的編譯器。所有沒有使用的訪問標誌,必須設置爲0。

  5、類名(this_class)

  接下來的兩個字節保存了一個常量池的索引。這個常量池中的實體必須是CONSTANT_CLSS_INTO類型的,他包含了標誌和名字索引。標誌就是 CONSTATN_CLASS,那個名字索引應該是一個保存了這個類或者接口全名的CONSTANT_UTF8_INFO類型的索引。

  6、父類(super_class)

  this_class之後的就是兩個字節的super_class,他也是一個常量池的索引,其中保存了父類的全名,處理this_class一樣。當父 類是java.lang.Object時,super_class都應該是0。對於接口super_class都是0。

  7、(interfaces_count and interfaces)

  interfaces_count中保存了父接口的個數,interfaces中以數組形式保存了一些常量池的索引。每一個索引都指向了一個 CONSTANT_CLASS_INFO的常量,其中保存了每一個父接口的全名。這個數組的順序就是父接口出現在在implements、extends 語句中從左到右的順序。

  8、(fields_count and fields)

  字段被保存在一個field_info的列表中,fields_count是這個列表的長度。Field_info列表中保存的只是類或者接口中的申明的變量,從父類或者父接口中繼承的字段不保存在這裏。

  每一個field_info表中的一條都描述了一個字段的信息,包括:字段名,描述符,訪問權限。如果一個字段被申明爲final,那麼這個字段的信息即會保存在field_info表中,也會保存在常量池中。

  9、(methods_count and methods)

  方法的信息都保存在method_info表中,mehtods_count是表的長度。Method_info表中只保存類或者接口中申明的方法,不保存從父類或者接口中繼承的方法。

  Method_info 表中保存了方法名和描述符(返回值和參數類型)。如果不是抽象方法,還會保存用於堆棧的大小(保存本地變量用的)、操作數堆棧的最大值、捕捉的異常列表、 方法的字節碼、可選的行號和本地變量表。如果方法拋出一些被檢查的異常,method_info還會包含一個被檢查異常的列表。

  10、(attributes_count and attributes)

  類文件中最後的就是屬性個數和atribute_info列表。Atribute_info表中保存了一些指向常量池中constant_utf8_info的索引,其中保存了屬性的名字。Java虛擬機規範中定義了兩種類型的屬性:源代碼和內部類。

三、特定字符串(Special Strings)

  常量池中的字符引用包含三種特定字符串:全限定名,簡單名,描述符。一個類或者接口的所有字符引用都必須包含一個全限定名。每一個字段或者方法都有一個簡 單名和描述符作爲全限定名的補充。這些特定字符串用來表示文件中定義的類和接口,包換類名,父類名,父接口名,每個字段和方法的簡單名和描述符。

  1、全名(Fully Qualified Names)

  當常量池中引用了類和接口時,就會提供這個類或者接口的權限定名,比如java.lang.Object。

  2、簡單名(Simple Names)

  字段和方法都以簡單名的形式保存在常量池中。比如常量池中有一個java.lang.Object類的String toString()方法的引用,就會保存“toString”;java.lang.System類的java.io.PrintStream out字段,被保存爲“out”。

  3、描述符(Descripters)

  字段和方法的字符引用都會包含一個描述符。字段的描述符提供了字段的類型。方法的描述符提供了方法的返回值、參數個數、參數類型。所有描述符得類型列表:

  FieldDescriptor:

  FieldType

  ComponentType:

  FieldType

  FieldType:

  BaseType

  ObjectType

  ArrayType

  BaseType:

  Terminal Type

  B byte

  C char

  D double

  F float

  I int

  J long

  S short

  Z boolean

  ObjectType:

  L;

  ArrayType:

  [ ComponentType

  ParameterDescriptor:

  FieldType

  MethodDescriptor:

  ( ParameterDescriptor* ) ReturnDescriptor

  ReturnDescriptor:

  FieldType

  V

  Table 6-6. Examples of field descriptors

  Descriptor Field Declaration

  I int i;

  [[J long[][] windingRoad;

  [Ljava/lang/Object; java.lang.Object[] stuff;

  Ljava/util/Hashtable; java.util.Hashtable ht;

  [[[Z boolean[][][] isReady;

  Table 6-7. Examples of method descriptors

  Descriptor Method Declaration

  ()I int getSize();

  ()Ljava/lang/String; String toString();

  ([Ljava/lang/String;)V void main(String[] args);

  ()V void wait()

  (JI)V void wait(long timeout, int nanos)

  (ZILjava/lang/String;II)Z boolean regionMatches(boolean ignoreCase, int toOffset, String other, int ooffset, int len);

  ([BII)I int read(byte[] b, int off, int len);

  四、常量池

  常量池被組織成爲一個cp_info類型的列表,表6-8顯示了cp_info表的結構

  Table 6-8. General form of a cp_info table

  Type Name Count

  u1 tag 1

  u1 info depends on tag value

  1、The CONSTANT_Utf8_info Table

  2、The CONSTANT_Integer_info Table

  3、The CONSTANT_Float_info Table

  4、The CONSTANT_Long_info Table

  5、The CONSTANt_Double_info Table

  6、The CONSTANT_Class_info Table

  7、The CONSTANT_String_info Table

  8、The CONSTANT_Fieldref_info Table

  9、The CONSTANT_Methodref_info Table

  10、The COMSTANT_InterfaceMethodref_info Table

  11、The CONSTANT_NameAndType_info Table

  五、Fields

  六、Methods

  七、Attributes


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章