JVM—加载到方法区的Class文件长什么样?
原文作者:zhaohong_bo
原文地址:深入理解 JVM Class文件格式(一)
目錄
一、JVM體系結構
二、class格式文件概述
三、class文件詳細介紹
一、JVM體系結構
二、class格式文件概述
class文件是一種8位字節的二進制流文件, 各個數據項按順序緊密的從前向后排列, 相鄰的項之間沒有間隙, 這樣可以使得class文件非常緊湊, 體積輕巧, 可以被JVM快速的加載至內存, 并且占據較少的內存空間。 我們的Java源文件, 在被編譯之后, 每個類(或者接口)都單獨占據一個class文件, 并且類中的所有信息都會在class文件中有相應的描述, 由于class文件很靈活, 它甚至比Java源文件有著更強的描述能力。
疑問:內部類和匿名類也會生成.class文件么?
class文件中的信息是一項一項排列的, 每項數據都有它的固定長度, 有的占一個字節, 有的占兩個字節, 還有的占四個字節或8個字節, 數據項的不同長度分別用u1, u2, u4, u8表示, 分別表示一種數據項在class文件中占據一個字節, 兩個字節, 4個字節和8個字節。 可以把u1, u2, u3, u4看做class文件數據項的“類型” 。
三、class文件詳細介紹
3.1 魔數
在class文件開頭的四個字節, 存放著class文件的魔數, 這個魔數是class文件的標志,他是一個固定的值: 0XCAFEBABE 。 也就是說他是判斷一個文件是不是class格式的文件的標準, 如果開頭四個字節不是0XCAFEBABE, 那么就說明它不是class文件, 不能被JVM識別。
下面是一個class文件的二進制形式
3.2 主版本號和次版本號
緊接著魔數的四個字節是class文件的次版本號和主版本號。 隨著Java的發展, class文件的格式也會做相應的變動。 版本號標志著class文件在什么時候, 加入或改變了哪些特性。 舉例來說, 不同版本的javac編譯器編譯的class文件, 版本號可能不同, 而不同版本的JVM能識別的class文件的版本號也可能不同, 一般情況下, 高版本的JVM能識別低版本的javac編譯器編譯的class文件, 而低版本的JVM不能識別高版本的javac編譯器編譯的class文件。 如果使用低版本的JVM執行高版本的class文件, JVM會拋出java.lang.UnsupportedClassVersionError。
如下圖,0034為主版本號,對應的十進制數為:50,查看下面圖,可知50對應的是JDK1.6,也就是說該class文件可被JDK1.6以上的虛擬機執行
3.3 class文件中的常量池
在class文件中, 位于版本號后面的就是常量池相關的數據項。 常量池是class文件中的一項非常重要的數據。 常量池中存放了字符串, 常量值, 當前類的類名, 字段名, 方法名, 各個字段和方法的描述符, 對當前類的字段和方法的引用信息, 當前類中對其他類的引用信息等等。 常量池中幾乎包含類中的所有信息的描述, class文件中的很多其他部分都是對常量池中的數據項的引用,比如后面要講到的this_class, super_class, field_info, attribute_info等, 另外字節碼指令中也存在對常量池的引用, 這個對常量池的引用當做字節碼指令的一個操作數。 此外, 常量池中各個項也會相互引用。
class文件中的項constant_pool_count的值為1, 說明每個類都只有一個常量池。 常量池中的數據也是一項一項的, 沒有間隙的依次排放。常量池中各個數據項通過索引來訪問, 有點類似于數組, 只不過常量池中的第一項的索引為1, 而不為0, 如果class文件中的其他地方引用了索引為0的常量池項, 就說明它不引用任何常量池項。class文件中的每一種數據項都有自己的類型, 相同的道理,常量池中的每一種數據項也有自己的類型。 常量池中的數據項的類型如下表:
每個數據項叫做一個XXX_info項, 比如, 一個常量池中一個CONSTANT_Utf8類型的項, 就是一個CONSTANT_Utf8_info 。除此之外, 每個info項中都有一個標志值(tag), 這個標志值表明了這個常量池中的info項的類型是什么, 從上面的表格中可以看出, 一個CONSTANT_Utf8_info中的tag值為1, 而一個CONSTANT_Fieldref_info中的tag值為9 。
JVM常量池中各數據項類型詳解,傳送門
Java程序是動態鏈接的, 在動態鏈接的實現中, 常量池扮演者舉足輕重的角色。 除了存放一些字面量之外, 常量池中還存放著以下幾種符號引用:
(1) 類和接口的全限定名
(2) 字段的名稱和描述符
(3) 方法的名稱和描述符
在詳細講解常量池中的各個數據項之前, 我們有必要先了解一下class文件中的特殊字符串, 因為在常量池中, 特殊字符串大量的出現,這些特殊字符串就是上面說的全限定名和描述符。 要理解常量池中的各個數據項, 必須先了解這些特殊字符串。
class文件中的特殊字符串介紹見這里,傳送門
————————————————
版權聲明:本文為CSDN博主「zhaohong_bo」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/zhaohong_bo/article/details/89399715
總結
以上是生活随笔為你收集整理的JVM—加载到方法区的Class文件长什么样?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM—方法区到底是怎么保存函数方法的?
- 下一篇: 动态规划—01背包问题