天天看點

關于Class檔案

Java人對class檔案肯定很熟悉了,它是Java源碼編譯後的産物。JVM運作時負責加載class檔案,并根據class定義的執行邏輯運作。java為了将硬體底層的差異屏蔽掉,引入了Java虛拟機(JVM)并将硬體差異處理都放到JVM中,是以可以編譯出統一的二進制檔案——class。是以隻要通過編譯器編譯成規範的class檔案都可以在JVM上面運作,像現在很多其他語言其實都是編譯成class檔案并運作在JVM上,例如Scala、JRuby、Groovy、Clojure等等。

class位元組碼作為java虛拟機的語言,java虛拟機規範規定了class檔案的結構,JVM運作時類加載器就會對這些class位元組碼進行加載。這裡并不深入讨論JVM對于class位元組碼的處理,而是主要了解class檔案的結構,因為tomcat的實作涉及到了class相關知識。

每個class檔案包含一個類或者接口的Java類型,class檔案以8位位元組為基礎的二進制流,每個資料項的順序和占用位元組數都有嚴格的規定。一個class檔案的基本結構如下:

<code>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[attribute_count]; }</code>

class檔案結構主要包含兩種資料類型,其中u開頭表示無符号數,u1表示1個位元組,u2表示2個位元組,u4表示4個位元組;另外一些為xxx_info,它是一種表結構,裡面又包含了若幹的無符号數和表結構。

①magic,即魔數,每個class檔案開頭4個位元組,它的值固定為0xCAFEBABE,用于辨別是否為class檔案。

②minor_version和major_version,表示編譯器使用的JDK的副版本和主版本,高版本編譯的class檔案可以向下相容低版本,即高版本JDK可以運作低版本的class,而低版本的JDK不能運作高版本的class。

③constant_pool_count,表示常量池計數器,但這裡有個比較特殊的地方,假如它的值為100,則常量池的常量數為99個。因為常量池的計數是從1開始的。

④constant_pool,表示常量池的資料集合,常量池中每個常量都是一個表結構表示,這些表結構一共包括11種,其中主要包括的類型為:utf-8字元串、整型、浮點型、長整型、雙精度浮點型、類或接口引用、字元串類型、字段引用、類方法引用、接口方法引用、名稱和類型引用。

⑤access_flags,表示通路辨別,用于辨別類或接口的通路資訊,例如是否為public類型、是否被聲明為final、是否是一個接口、是否為abstract類型、是否為注解、是否為枚舉等等。

⑥this_class,表示此類的全限定名(全限定名的格式:例如com.test.MyTomcat”類的全限定名為”com/test/MyTomcat;”)。

⑦super_class,表示此類的父類的全限定名。

⑧interfaces_count,表示此類實作接口的計數器,如果為3,則表示實作了3個接口。

⑨interfaces,表示類實作的接口集,它的每個值都必須是常量池裡的有效引用。

⑩fields_count,表示字段計數器。

⑪fields,表示類的字段集,每個字段表結構包括:通路辨別、字段名引用、字段描述符引用、屬性計數器、屬性表結構集等等。其中字段描述符使用了簡稱表示,例如B表示byte類型,所有的類型包括:B-byte、C-char、D-double、F-float、I-int、J-long、S-short、Z-boolean、V-void、L-對象類型,如:Ljava/lang/String;。除此之外數組則用 [ 表示,例如double[][] d的類型為 [[D ,而String[] s的類型則為[Ljava/lang/String。

⑫methods_count,表示方法計數器。

⑬methods,表示類的方法集,每個方法表結構包括:通路辨別、方法名引用、方法描述符引用、屬性計數器、屬性表結構集等等。其中方法描述符應該按先參數清單,後傳回值的順序進行描述,而且參數清單按照參數順序放”()”之内,如:方法”String get(long id,String name)”的描述符為”(J,Ljava/lang/String;)Ljava/lang/String;”

⑭attributes_count,表示class的屬性計數器。

⑮attributes,表示class的屬性,屬性表結構集不要求嚴格的順序,隻要屬性名稱不與存在的屬性名重複即可,虛拟機規範中規定了9個屬性,除此之外還可以自己定義一些屬性并自己實作編譯器把屬性添加到class檔案中,JVM運作時會把不能識别的屬性忽略,而不會影響運作。是以添加了屬性還得JVM支援才行。

========廣告時間========

<a href="http://blog.csdn.net/wangyangzhizhou/article/details/74080321">為什麼寫《Tomcat核心設計剖析》</a>

=========================

歡迎關注:

關于Class檔案