JVM-常量池,jvm-常量
在.java文件,講過javac編譯後產生的 .class文件中,頭4個字節表示的是魔數,接著魔數後面的第5,6個字節存儲的是次版本號,第7,8個字節存儲的主板本號.那麼再接下來的就是表示常量池入口了.
常量池
可以理解為class文件之中的資源倉庫,它是class文件結構中與其他項目關聯最多的數據類型,也是占用class文件空間最大的數據項目之一,同時它還是class文件中第一個出現表類型的數據項目.
由於常量池的數量是不固定的,所以在常量池入口需要放置一項u2(即2個字節)類型的數據,代表常量池容量計數值(constant-pool-count)(從1開始,將0表示不引用任何常量).
常量池中主要存放兩大類常量:字面量(Literal)和符號引用(Synbolic Reference).
- 字面量:比較接近於Java語言層面的常量概念,如文本字符串,聲明為final的常量值.
- 符號引用:包括如下三類常量:
常量池中每一項常量都是一個表(14種表).
類型
標志
描述
CONSTANT_utf8_info
1
UTF-8編碼的字符串
CONSTANT_Integer_info
3
整形字面量
CONSTANT_Float_info
4
浮點型字面量
CONSTANT_Long_info
5
長整型字面量
CONSTANT_Double_info
6
雙精度浮點型字面量
CONSTANT_Class_info
7
類或接口的符號引用
CONSTANT_String_info
8
字符串類型字面量
CONSTANT_Fieldref_info
9
字段的符號引用
CONSTANT_Methodref_info
10
類中方法的符號引用
CONSTANT_InterfaceMethodref_info
11
接口中方法的符號引用
CONSTANT_NameAndType_info
12
字段或方法的符號引用
CONSTANT_MothodType_info
16
標志方法類型
CONSTANT_MethodHandle_info
15
表示方法句柄
CONSTANT_InvokeDynamic_info
18
表示一個動態方法調用點
注意:在這14種表有一個共同的特點,就是開始的第一位是一個u1類型的標志位(tag,就是上表中的標志這一列),代表當前這個常量屬於哪種常量類型.下面分析實例的時候會用到.
由於class文件中方法,字段等都需要引用CONSTANT_utf8_info類型常量來描述名稱,所以CONSTANT_utf8_info類型常量的最大長度也就是Java中方法,字段名的最大長度(Java程序中如果定義了超過64KB英文字符的變量或方法名,將無法編譯).
下面我們接著上一篇分析的class文件繼續往下走.
這張圖中,我們繼續分析了接著主版本號接下來的幾個字節,首先是常量池入口是0x0013,轉化為十進制就是19,那麼表示的范圍就是1~18,因為0用來表示不引用任何常量池了.那麼也就是說0x0013之後有18個常量池.我們看緊接著的一個常量池,十六進制0x0a用十進制表示就是10,通過上表的標志列我們可以直到,10對應的那一行就是CONSTANT_Methodref_info類型的表,是類中方法的符號引用.那麼知道了是CONSTANT_Methodref_info表,就可以根據CONSTANT_Methodref_info表的結構繼續往下分析,一直到分析完18個常量池.在這裡就不一一往下分析了,直接通過javap工具來直接查看,也順便查看我們分析的對不對.
我們從javap的結果看出,常量池的范圍就是1~18,然後第一個常量池就是Method,也即CONSTANT_Methodref_info.