Class 文件中的常量池是 最複雜、最關鍵 的數據區域。Java 作為動態連結語言,編譯期不解析最終內存地址,而是將符號引用 (類全限定名、字段/方法名稱描述符) 存入常量池,由虛擬機在連結階段解析。這與 C 語言靜態連結 (編譯期固定偏移量) 形成本質差異。
| 常量類型 | 標籤值 | 說明 |
|---|---|---|
| CONSTANT_Utf8 | 1 | UTF-8 編碼 Unicode 字符串 |
| CONSTANT_Integer | 3 | int 常量 |
| CONSTANT_Float | 4 | float 常量 |
| CONSTANT_Long | 5 | long 常量 (佔 2 个槽位) |
| CONSTANT_Double | 6 | double 常量 (佔 2 个槽位) |
| CONSTANT_Class | 7 | 類/介面符號引用 |
| CONSTANT_String | 8 | String 常量 |
| CONSTANT_Fieldref | 9 | 字段符號引用 |
| CONSTANT_Methodref | 10 | 類方法符號引用 |
| CONSTANT_InterfaceMethodref | 11 | 介面方法符號引用 |
| CONSTANT_NameAndType | 12 | 名稱與類型符號引用 |
// 常量池項體聯合體 - 統一大小便於數組索引
union constantPoolEntryStruct {
struct { unsigned short classIndex; unsigned short nameTypeIndex; } method; // 也用於 Fieldref
CLASS clazz;
INTERNED_STRING_INSTANCE String;
cell *cache; // 指向 clazz 或 String
cell integer;
long length;
NameTypeKey nameTypeKey;
NameKey nameKey;
UString ustring;
};
// 常量池結構
struct constantPoolStruct {
union constantPoolEntryStruct entries[1]; // 柔性數組,實際長度由 entries[0] 存儲
};
entries[0] 不存實際常量,而是存常量項總數 (對應 Class 文件 constant_pool_count - 1),這與 Class 文件格式完全一致RawPoolint tableSize = numberOfEntries + ((numberOfEntries + 3) >> 2);
公式解析:constantPoolEntryStruct 大小為 4 字節。項體數組後需緊跟標籤 byte 數組 (每項 1 byte)。以 4 字節對齊分配:每 4 個標籤佔 1 個槽位。(n+3)>>2 即向上取整除以 4。
RawPool,轉換並填入正式常量池CONSTANT_Utf8:解碼為 KVM 內部 UString (Unicode 字符串)CONSTANT_Class:解析為 CLASS 結構指標 (可能觸發遞歸載入)CONSTANT_String:建立 INTERNED_STRING_INSTANCE (字符串常量池化)Fieldref/Methodref/InterfaceMethodref:統一存為 method 結構 (classIndex, nameTypeIndex)NameAndType:存為 NameTypeKey| Class 文件 | KVM 運行時 | 備註 |
|---|---|---|
constant_pool_count | entries[0] (項數) | 計數包含自身,故實際項數 = count - 1 |
constant_pool[1...count-1] | entries[1...count-1] | 項體數據 |
| 無顯式類型數組 | 項體數組後的 byte 數組 | KVM 顯式分離類型標籤 |
| 索引從 1 開始 | 索引從 1 開始 (0 為計數) | 完全一致 |
invokevirtual 等)、字段存取 (getfield 等) 皆通過常量池索引解析符號引用ldc 指令載入 CONSTANT_String 時返回駐留實例CONSTANT_Class 可能觸發目標類載入CONSTANT_Integer/Float/Long/Double 直接內嵌字節碼KVM 常量池設計精確映射 Class 文件規範,通過 聯合體統一槽位大小、首槽位存計數、類型標籤後置數組 三大技巧,實現了緊湊、高效、易於索引的運行時常量池結構。理解此機制對於 JVM 內部原理、類載入器、字節碼操作工具開發具有核心價值。