程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Class文件格式 詳解

Class文件格式 詳解

編輯:關於JAVA
 

Java編譯過程是將Java文件轉換為Claaa文件,從而實現了跨平台的功能, 本文詳細講述Class文件結構。

一、 概述

計算機只能識別0和1,所以大家編寫的程序都需要經過編譯器,轉換為由0和1組成的二進制本地機器碼(Native Code)。隨著虛擬機的不斷發展,很多程序語言開始選擇與操作系統和機器指令集無關的格式作為編譯後的存儲格式(Class文件),從而實現”Write Once, Run Anywhere”。 Java設計之初,考慮後期能讓Java虛擬機運行其他語言,目前有越來越多的其他語言都可以直接需要在Java虛擬機,虛擬機只能識別Class文件,至於是由何種語言編譯而來的,虛擬機並不關心,如下圖:

Jvm_class_loading_1

可以看出不管是由Java語言,還是JRuby等其他語言,只能能生成.class字節碼文件,就都可以運行在Java虛擬機上。故發布規范文檔時,Java規范拆分為Java語言規范和Java虛擬機規范。

Java語法中定義各種變量、關鍵字、運算符的語義最終由多個字節碼命令組合而成。因此字節碼命令所能提供的語義描述能力必然要比Java語言本身更加強大。

二、Class組成

Class文件是一組以8位字節為單位的二進制流,中間沒有任何分隔符,非常緊湊。 當需要占用8位以上的數據時,會按照Big-endian順序,高位在前,低位在後的方式來分割成多個8位字節來存儲。

  • 任何一個Class文件都對應著唯一的類或接口的定義信息;
  • 類或接口並不一定定義在文件裡,也可以通過類加載器直接生成。

Java虛擬機規范規定:Class文件格式采用偽結構來存儲數據,偽結構中只有無符號數和表這兩種數據類型。

  • 無符號數:是基本數據類型,以u1、u2、u4、u8分別代表1個字節、2個字節、4個字節、8個字節的無符號數。無符號數用於描述數字、索引引用、數量值、字符串值。
  • 表:是由多個無符號數或者子表作為數據項構成的符合數據類型。用於描述有層次關系的復合結構的數據。整個Class其實就是一張表。

2.1 相關概念

下面介紹幾個概述:

全限定名

是指把類全名中的“.”號,用“/”號替換,並且在最後加入一個“;”分號後生成的名稱。比如java.lang.Object對應的全限定名為java/lang/Object;

簡單名

這個比較好理解,就是直接的方法名或者字段。比如toString()方法,不需要包名作為前綴了。

字段描述符

用於描述字段的數據類型。

規則如下:

基本類型字符 對應類型 B byte C char D double F float I int S short J long Z boolean V void L+classname +; 對象類型 [ 數組類型

例如:

  • 基本類型:int ==> I
  • 對象類型:String ==> Ljava/lang/String;
  • 數組類型:long[] ==> [J

方法描述符

用來描述方法的參數列表(數量、類型以及順序)和返回值。

格式:(參數描述符列表)返回值描述符。 例如:Object m(int i, double d, Thread t) {..} ==> IDLjava/lang/Thread;)Ljava/lang/Object;

2.2 ClassFile結構

一個Class類文件是由一個ClassFile結構組成:

ClassFile {
    u4             magic;               //魔數,固定值0xCAFEBABE
    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[attributes_count];          //具體的屬性內容
}

一個Class文件的大小:26 + cp_info[] + u2[] + field_info[] + method_info[] + attribute_info[]

接下來,將具體來介紹ClassFile文件的各個組成部分。

三、ClassFile文件組成

3.1 魔數

每個Class文件頭4個字節稱為魔數(Magic Number),作用是用於確定這個Class文件是否能被虛擬機所接受,魔數固定值0xCAFEBABE。這是身份識別,比如jpeg等圖片文件頭也會有魔數。

3.2 版本號

緊跟魔數,也占用4個字節。從第5字節到第8字節存儲的分別是 次版本號,主版本號。

3.3 常量池

常量池是Class文件空間最大的數據項之一,長度不固定。

a. 常量池長度 用u2類型代表常量池容量計數值,u2緊跟版本號。u2的大小等於常量池的常量個數+1。對於u2=0的特殊情況,代表沒有使用常量池。

b. 常量池內容,格式如下:

cp_info {
    u1 tag;
    u1 info[];
}

包括兩個類常量,字面量和符號引用:

  • 字面量:與Java語言層面的常量概念相近,包含文本字符串、聲明為final的常量值等。
  • 符號引用:編譯語言層面的概念,包括以下3類:
    • 類和接口的全限定名
    • 字段的名稱和描述符
    • 方法的名稱和描述符

常量池中每一項常量都是一個表結構,每個表的開始第一位是u1類型的標志位tag, 代表當前這個常量的類型。在JDK 1.7.中共有14種不同的表結構的類型,如下:

constant_type

Class文件都是二進制格式,可通過Jdk/bin/javap.exe工具,分析Class文件字節碼。關於javap用法,可通過javap --help來查看。  

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