唔。。在解析前,先給大家介紹下Class類文件結構吧。
Class文件格式採用的是一種類似C語言結構體的僞結構來存儲數據,這種僞結構中只有兩種類型:無符號數和表。
無符號數屬於基本的數據類型,用u1,u2,u4,u8來代表1個字節,2個字節,4個字節,8個字節的無符號數,可以用來描述數字、索引、數量值等。
表是由多個無符號數或者其他表作爲數據構成的複合數據類型,所有表都習慣性以“_infor”結尾,整個Class文件本質上就是一張表。
下面是Class文件的結構。
Class文件就是嚴格按照這個格式來存儲數據的。
唔。。多說無益,直接上例子吧。
public class tt {
private int m;
public int inc() {
return m + 1;
}
}
這個我們tt.java的代碼,下面,我們就要把這個tt.java編譯後的tt.class文件,給解析出來。
首先,javac 命令tt.java編譯成tt.class
然後,用16進制查看器查看tt.class文件
這就是class文件了,下面我們按照上面的class文件結構來一步一步分析。
1.magic魔數和minor_version、major_version。
每個class文件的頭4個字節稱爲魔數,它的唯一作用就是確定這個文件是能被jvm解析的class文件。很多不同格式的文件都是通過魔數來進行識別的,比如gif或者jpeg等文件頭中都有魔數。
class文件的魔數是固定的值爲:0xCAFEBABA,這和我們class文件結構圖中的描述一致,是u4類型的數據。
之後是Class文件的版本號,minor_version是次版本號,值爲0x0000,major_version是主版本號,值分別是0x0034,也就是十進制的52,也就是JDK1.8版本編譯的。
下面是Class文件版本號
2.常量池
接着版本號之後的是常量池:constant_pool_count,constant_pool。
constant_pool_count代表的是常量池的數量,這個數量的計數是從1開始,而不是0開始的。
在該例子中,常量池數量爲十六進制數0x0013,即十進制的19,因爲計數是從1開始,所以,這常量池的數量爲19-1=18。
跟在常量池數量之後的是具體的常量池內容。常量池中主要存放兩大類常量:字面量和符號引用,字面量也就是字符串、final類型的常量值等,符號引用則是編譯方面的概念。
在JDK1.7之前一共有11種結構各不相同的表結構。這些表都有一個共同特點,第一位是u1類型的標誌位,用來標緻是哪種類型的常量。下面是標誌相對應的常量類型。
詳細的常量類型結構我這裏就不寫了,這裏只寫例子中所用到的類型結構。建議大家參考《深入理解java虛擬機》第6章。
唔。。。。
寫到這裏突然不想寫了,因爲class類文件結構不難,同時,覺得自己這篇博客寫的沒什麼實際意義。
第一,寫給自己做總結吧,也沒總結到啥,因爲真的不難,沒啥好總結的感覺,
第二,寫給大家看吧,大家還不如看書,書裏講的很詳細,要是有不懂的,可以留言交流。
唔。。
也可以參考我寫的解析代碼:https://github.com/ZheBigFish/myjvm,ch03寫的就是類文件解析
唔,建議大家多看書。
最後,本文參考自《深入理解java虛擬機》第6章。
OK,此貼終結。