程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> jvm理論-class文件,jvm理論-class

jvm理論-class文件,jvm理論-class

編輯:JAVA綜合教程

jvm理論-class文件,jvm理論-class


當JVM運行Java程序的時候,它會加載對應的class文件,並提取class文件中的信息存放在JVM的方法區內存中。

Class文件組成

1、Class文件是一組以8位字節為基礎單位的二進制流,各個數據項目嚴格按順序緊湊排列在Class文件中,中間沒有分隔符。所以Class文件中存儲的內容幾乎全部是程序運行的必要數據。

2、當遇到占據8位字節以上空間的數據項時,會按照高位在前的方式, 分割成若干個8位字節進行存儲。

Class文件數據類型

無符號數

1、基本數據類型,以u1、u2、u4、u8分別代表1個字節、2個字節、4個字節、8個字節。

2、無符號數可以用來描述數字、索引引用、數量值和按照UTF8編碼構成字符串值。

1、表用來描述有層次關系的的復合數據結構。

2、表是由無符號數或者其他表作為數據項構成的復合數據結構。

3、所有表都以_info結尾。

4、整個class文件本質上就是一張表。

item1:magic(魔數)[u4]:0xCAFEBABE

辨別class文件與非class文件

item2:minor_version、major_version(次、主版本號) [u2,u2]

隨著Java技術的發展,class文件的格式會發生變化。版本號的作用在於使得虛擬機能夠認識當前加載class的文件格式。從而准確的提取class文件信息。

item3:常量池(constant_pool_count 、constance_pool)[u2,cp_info]

常量池內容

常量池存放兩大類常量:字面量(Literal)和符號引用(Synbolic Reference)

一、字面量

1、文本字符串

2、聲明為final的常量值

final修飾的變量有三種:靜態變量、實例變量和局部變量,分別表示三種類型的常量

3、基本數據類型

4、其他

二、符號引用

類和接口的全限定名(Fully Qualified Name)
字段的名稱和描述符(Descriptor)
方法的名稱和描述符

常量池結構

JVM會將每一個常量構成一個常量表,每個常量表都有自己的入口地址。而實際上在JVM會將這些常量表存儲在方法區中一塊連續的內存空間中,因此class文件會根據常量表在常量池中的位置對其進行索引。比如常量池中的第一個常量表的索引值就是1,第二個就是2。有的時候常量表A需要常量表B的內容,則在常量表A中會存儲常量表B的索引值x。而constant_pool_count就記錄了有多少個常量表,或則所有多少個索引值。實際上,常量池中沒有索引值為0的常量表,但這缺失的索引值也被記錄在 constant_pool_count中,因此 constant_pool_count等於常量表的數量加1。

常量池計數器(constant_pool_count):常量表(cp_info)數量+1。

常量表(cp_info):constant_pool_count-1個。

常量表結構(cp_info)

每個常量表(cp_info) 都會對應記錄著class文件中的某中類型的字面量

這14種表有一個共同的特點,就是開始的第一位是一個u1類型的標志位(tag,就是上表中的標志這一列),代表當前這個常量屬於哪種常量類型。

 

字符串常量池:http://www.cnblogs.com/tenghoo/p/jvm_string.html

基本類型常量池:http://www.cnblogs.com/tenghoo/p/jvm_primitive.html

item4:訪問標志(access_flags)[u2]  

表明該class文件中定義的是類還是接口,訪問修飾符是public還是缺省。類或接口是否是抽象的。類是否是final的。

item5:類索引(this_class) [u2]、父類索引(super_class)[u2]、接口索引集合(inteface_count、interfaces )[u2,u2]

1、Class文件通過這三項數據來確定這個類的繼承關系。

2、類索引用於確定這個類的全限定名。

3、父類索引用於確定這個類的父類的全限定名。由於Java語言不允許多重繼承,所以父類索引只有一個。

4、除了java.lang.Object之外,所有的Java類都有父類,因此除了java.lang.Object外,所有Java類的父類索引都不為0。

5、接口索引集合就用來描述這個類實現了哪些接口。

6、類索引和父類索引用兩個u2類型的索引值表示,它們各自指向一個類型為CONSTANT_Class_info的類描述符常量,通過CONSTANT_Class_info類型的常量中的索引值可以找到定義在CONSTANT_Utf8_info類型的常量中的全限定名字符串。

7、對於接口索引集合,入口的第一項:u2類型的數據為接口計數器(interfaces_count),表示索引表的容量。如果該類沒有實現任何接口,則該計數器值為0,後面接口的索引表不再占用任何字節。

item6:字段表集合(field_count,fields) [u2,field_info]

1、字段表(field_info)用於描述接口或者類中聲明的變量。

2、字段(field)包括類級變量以及實例級變量,但不包括在方法內部聲明的局部變量。

field_info表格式

access_flags(2byte 訪問修飾符)

name_index(2byte 存儲字段名的常量表在常量池中的索引)

description_index(2byte 存儲字段的所屬類型的常量表在常量池中的索引)

attribute_count(2byte 屬性表的數量)

attribute (屬性)

其中attribute是由多個attribute_info組成。而JVM規范定義了字段的三種屬性:ConstanceValue、Deprecated和Synthetic。

 

 

 

item7:方法表集合(method_count、methods) [u2,method_info] 

method_count、methods 與字段類似,method_count表明類中方法的數量和每個方法的常量表的索引。methods表明了不同長度的method_info表的序列。

method_info表格式

access_flags(2byte 訪問修飾符)

name_index(2byte 存儲方法名的常量表在常量池中的索引)

description_index(2byte 存儲方法的返回類型和參數類型的常量表在常量池中的索引)

attribute_count(2byte 屬性表的數量)

attribute (屬性)

其中方法的屬性JVM規定了四種:Code,Deprecated,Exceptions,Synthetic。

 

簡單名稱:方法名如:fun,字段名如:str1

全限定名:com/mobjia/clazz/TestClass

描述符:

描述符的作用是用來描述字段的數據類型、方法的參數列表(包括數量、類型以及順序)和返回值。

根據描述符規則,基本數據類型(byte、char、double、float、int、long、short、boolean)以及代表無返回值的void類型都用一個大寫字符來表示,而對象類型則用字符L加對象的全限定名來表示。

數組類型:每一維度將使用一個前置的“[”字符來描述,如一個定義為“java.lang.String[][]”類型的二維數組,將被記錄為:“[[Ljava/lang/String;”,一個整型數組“int[]”將被記錄為“[I”。

用描述符來描述方法時,按照先參數列表,後返回值的順序描述,參數列表按照參數的嚴格順序放在一組小括號“()”之內。

void inc()的描述符為()V
java.lang.String toString()的描述符()Ljava/lang/String;
int indexOf(char[]source,int sourceOffset,int sourceCount,char[]target,int targetOffset,inttargetCount,int fromIndex)的描述符 ([CII[CIII)I

 

Class實例分析

工具:WinHe十六進制編輯器

 

參考:

http://blog.csdn.net/luanlouis/article/details/39960815

http://blog.csdn.net/a616413086/article/details/52250638

http://hxraid.iteye.com/blog/687660

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved