學會閱讀Java位元組碼__Java

來源:互聯網
上載者:User

原文:http://blog.csdn.net/dc_726/article/details/7944154


1.Class檔案基礎
(1)檔案格式


Class檔案的結構不像XML等描述語言那樣鬆散自由。由於它沒有任何分隔字元號, 所以,以上資料項目無論是順序還是數量都是被嚴格限定的。哪個位元組代表什麼 含義,長度是多少,先後順序如何,都不允許改變。
(2)資料類型
仔細觀察上面的Class檔案格式,可以看出Class檔案格式採用一種類似於C語言 結構體的偽結構來儲存,這種偽結構中只有兩種資料類型:無符號數和表。 無符號數就是u1、u2、u4、u8來分別代表1個、2個、4個、8個位元組。表是由 多個無符號數或其他表構成的複合資料型別,以“_info”結尾。在表開始位置, 通常會使用一個前置的容量計數器,因為表通常要描述數量不定的多個資料。
下圖表示的就是Class檔案格式中按順序各個資料項目的類型:


(3)相容性
高版本的JDK能向下相容以前版本的Class檔案,但不能運行以後版本的Class檔案, 即使檔案格式未發生任何變化。舉例來說,JDK 1.7中的JRE能夠執行JDK 1.5編譯 出的Class檔案,但是JDK 1.7編譯出來的Class檔案不能被JDK 1.5使用。這就是 target參數的用處,可以在使用JDK 1.7編譯時間指定-target 1.5。

2.一個簡單的例子 [java]  view plain  copy package com.cdai.jvm.bytecode;      public class ByteCodeSample {          private String msg = "hello world";              public void say() {           System.out.println(msg);       }          }   編譯成Class檔案後的樣子:



3.逐個位元組分析
(1)魔數和版本號碼


前四個位元組(u4)cafebabe就是Class檔案的魔數,第5、6位元組(u2)是Class檔案的 次版本號碼,第7、8位元組(u2)是主要版本號。十六進位0和32,也就是版本號碼為50.0, 即JDK 1.6。之前介紹的target參數會影響這四個位元組的值,從而使Class檔案相容不同 的JDK版本。
(2)常量池


常量池是一個表結構,並且就像之前介紹過的,在表的內容前有一個u2類型的計數器, 表示常量池的長度。十六進位23的十進位值為35,表示常量池裡有下標為1~34的表項。 下標從1開始而不是0,是因為第0個表項表示“不引用常量池中的任意一項”。每個表項 的第一個位元組是一個u1類型,表示12中資料類型。具體含義如下:


以第一項07 00 02為例,07表示該常量是個CONSTANT_Class_info類型,緊接著一個u2 類型的索引執行第2項常量。再看第二項01 00 24 63 6f 6d 2f ... 65表示的就是字串 類型,長度為36(十六進位00 24),緊接著就是UTF-8編碼的字串"com/cdai/jvm/bytecode /ByteCodeSample"。很容易讀懂吧。常量池主要是為後面的欄位表和方法表格服務的。
下面是通過javap解析後常量池的全貌(執行javap -c -l -s -verbose ByteCodeSample)
  Constant pool:
const #1 = class        #2;     //  com/cdai/jvm/bytecode/ByteCodeSample
const #2 = Asciz        com/cdai/jvm/bytecode/ByteCodeSample;
const #3 = class        #4;     //  java/lang/Object
const #4 = Asciz        java/lang/Object;
const #5 = Asciz        msg;
const #6 = Asciz        Ljava/lang/String;;
const #7 = Asciz        <init>;
const #8 = Asciz        ()V;
const #9 = Asciz        Code;
const #10 = Method      #3.#11; //  java/lang/Object."<init>":()V
const #11 = NameAndType #7:#8;//  "<init>":()V
const #12 = String      #13;    //  hello world
const #13 = Asciz       hello world;
const #14 = Field       #1.#15; //  com/cdai/jvm/bytecode/ByteCodeSample.msg:Ljava/lang/String;
const #15 = NameAndType #5:#6;//  msg:Ljava/lang/String;
const #16 = Asciz       LineNumberTable;
const #17 = Asciz       LocalVariableTable;
const #18 = Asciz       this;
const #19 = Asciz       Lcom/cdai/jvm/bytecode/ByteCodeSample;;
const #20 = Asciz       say;
const #21 = Field       #22.#24;        //  java/lang/System.out:Ljava/io/PrintStream;
const #22 = class       #23;    //  java/lang/System
const #23 = Asciz       java/lang/System;
const #24 = NameAndType #25:#26;//  out:Ljava/io/PrintStream;
const #25 = Asciz       out;
const #26 = Asciz       Ljava/io/PrintStream;;
const #27 = Method      #28.#30;        //  java/io/PrintStream.println:(Ljava/lang/String;)V
const #28 = class       #29;    //  java/io/PrintStream
const #29 = Asciz       java/io/PrintStream;
const #30 = NameAndType #31:#32;//  println:(Ljava/lang/String;)V
const #31 = Asciz       println;
const #32 = Asciz       (Ljava/lang/String;)V;
const #33 = Asciz       SourceFile;
const #34 = Asciz       ByteCodeSample.java;          

(3)訪問標誌




顯然,00 21表示的就是公有的類。
(4)類、父類、介面


這三個u2類型的值分別表示類索引1、父類索引3、介面索引集合0。查看之前的常量池, 第1項為"com/cdai/jvm/bytecode/ByteCodeSample",第3項為"java/lang/Object"。第0項 表示此類沒有實現任何介面,這也就是常量池第0項的作用。
(5)欄位表


00 01表示有1個欄位。00 02是欄位的訪問標誌,表示private許可權的。00 05是欄位的名稱 索引,指向常量池裡第5項"msg"。00 06是欄位的 描述符索引,指向常量池裡的第6項 "Ljava/lang/String"。最後的00 00表示該欄位沒有其他 屬性工作表了。
描述符的作用就是用來描述欄位的資料類型、方法的參數列表和傳回值。而屬性工作表就是為 欄位表和方法表提供額外資訊的表結構。對於欄位來說,此處如果將欄位聲明為一個static final msg = "aaa"的常量,則欄位後就會跟著一個屬性工作表,其中存在一項名為ConstantValue, 指向常量池中的一個常量,值為的"aaa"。
屬性工作表不像Class檔案中的其他資料項目那樣具有嚴格的順序、長度和內容,任何人實現的編譯器 都可以向屬性工作表中寫入自己定義的屬性資訊,JVM會忽略掉它不認識的屬性。後面的方法表中 還要用到屬性工作表的Code屬性,來儲存方法的位元組碼。
(6)方法表


00 02表示有兩個方法。00 01是方法的訪問標誌,表示公有方法。00 07和00 08與欄位表中的名稱 和描述符索引相同,在這裡分別表示"<init>"和"()V"。00 01表示該方法有屬性工作表,屬性名稱為00 09 即我們前面提到的Code屬性。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.