天天看點

Java Class位元組碼知識點回顧

把之前的筆記重新整理了一下,發上來供對java class檔案結構的有興趣的同學參考一下,也算對以前知識的回顧。

java class檔案打破了c或者c++等語言所遵循的傳統,用這些傳統語言寫的程式通常首先被編譯,然後被連接配接成單獨的、專門支援特定硬體平台和作業系統的二進制檔案。通常情況下,一個平台上的二進制可執行檔案不能在其他平台上工作。

java class檔案是可以運作在任何支援java虛拟機的硬體平台和作業系統上的二進制檔案,class檔案中包含了java虛拟機指令集和符号表以及若幹其他輔助資訊。作為一個通用的、機器無關的執行平台,任何其他語言的實作者都可以将java虛拟機作為語言的産品傳遞媒介。例如,使用java編譯器可以把java代碼編譯成存儲位元組碼的class檔案,使用grooy等其他語言的編譯器一樣可以把程式代碼編譯成class檔案,虛拟機并不關心class的來源是何種語言。

Java Class位元組碼知識點回顧

class檔案是一組以8位位元組位基礎機關的二進制流,采用一種類似c語言結構體的僞結構來存儲資料,這種僞結構隻有兩種資料類型:<code>無符号數</code>和<code>表</code>。無符号數屬于基本的資料類型,以u1、u2、u4、u8分别代表1個位元組、2個位元組、4個位元組、8個位元組的無符号數,無符号數可以用來描述數字、索引引用、數量值或utf-8編碼構成的字元串值。表是由多個無符号數或其他表作為資料項構成的複合資料類型,所有表都習慣性地以_info結尾。

每一個 class 檔案對應于一個如下所示的 classfile 結構體:

借用下之前同學的圖能更清晰地表達:

Java Class位元組碼知識點回顧

本文以testclasscode.class源碼為例展開,testclasscode.java對應的java代碼如下:

testclasscode.class對應的位元組碼如下:

constant pool:

#1 = class #2 // com/test/doc/exp/testclasscode

#2 = utf8 com/test/doc/exp/testclasscode

#3 = class #4 // java/lang/object

#4 = utf8 java/lang/object

#5 = utf8 attribute_1

#6 = utf8 ljava/lang/string;

#7 = utf8 attribute_2

#8 = utf8 ljava/lang/integer;

#9 = utf8

#10 = utf8 ()v

#11 = utf8 code

#12 = methodref #3.#13 // java/lang/object."":()v

#13 = nameandtype #9:#10 // "":()v

#14 = utf8 linenumbertable

#15 = utf8 localvariabletable

#16 = utf8 this

#17 = utf8 lcom/test/doc/exp/testclasscode;

#18 = utf8 testinterface_1

#19 = utf8 testinterface_2

#20 = utf8 (ljava/lang/string;)ljava/lang/string;

#21 = utf8 param

#22 = utf8 sourcefile

#23 = utf8 testclasscode.java

struct field_info {

u2 access_flags;

u2 name_index;

u2 descriptor_index;

u2 attributes_count;

attribute_info attributes;

}

struct method {

u2 method_counts;

method_info[] method_infos;

struct method_info {

struct attribute_info {

u2 attribute_name_index;

u4 attribute_length;

u1 info[attribute_length];

struct code {

u2 max_stack;

u2 max_locals;

u4 code_length;

u1 code[code_length];

u2 exception_table_length;

exception_info exception_table;

u2 attribute_count;

struct linenumbertable {

u2 line_number_table_length;

line_number_info line_number_table;