2.3 常量池
2.3.1 什麼是常量池?
緊接着版本号之後的就是常量池。常量池中存放兩種類型的常量:
-
字面量 (Literal)
接近Java語言的常量概念,如:字元串文本、final常量值。
-
符号引用 (Symbolic Reference)
屬于編譯原理方面,包括下面三類常量::
- 類和接口的全限定名
- 字段的名稱和描述符
- 方法的名稱和描述符
2.3.2 常量池的特點
-
長度不固定
常量池的大小不固定,是以常量池開頭放置一個u2類型的無符号數,代表目前常量池的容量.
該值從1開始,若為5表示池中有4項常量,索引值1~5
-
常量由二維表表示
開頭有個常量池容量計數值,接下來就全是一個個常量了,隻不過常量都是由一張張二維表構成,除了記錄常量的值以外,還記錄目前常量的相關資訊
- class檔案的資源倉庫
- 與本class中其它部分關聯最多的資料類型
- 占用Class檔案空間最大的部分之一 ,也是第一個出現的表類型項目
2.3.3 常量池中常量的類型
根據常量的資料類型不同,被細分為14種常量類型,都有各自的二維表示結構
每種常量類型的頭1個位元組都是tag,表示目前常量屬于14種類型中的哪一個.

以CONSTANT_Class_info常量為例,它的二維表示結構如下:
CONSTANT_Class_info表
- tag 表示目前常量的類型(目前常量為CONSTANT_Class_info,是以tag的值應為7,表一個類或接口的全限定名);
- name_index 表示這個類或接口全限定名的位置.它的值表示指向常量池的第幾個常量.它會指向一個CONSTANT_Utf8_info類型的常量
CONSTANT_Utf8_info表字元串常量
- tag 表目前常量的類型,這裡是1
- length 表該字元串的長度
- bytes為這個字元串的内容(采用縮略的UTF8編碼)
Java中定義的類、變量名字必須小于64K
類、接口、變量等名字都屬于符号引用,它們都存儲在常量池中
而不管哪種符号引用,它們的名字都由CONSTANT_Utf8_info類型的常量表示,這種類型的常量使用u2存儲字元串的長度
由于2位元組最多能表示65535個數,是以這些名字的最大長度最多隻能是64K
UTF-8編碼 VS 縮略UTF-8編碼
前者每個字元使用3個位元組表示,而後者把128個ASCII碼用1位元組表示,某些字元用2位元組表示,某些字元用3位元組表示。
Demo1.txt中的常量池部分
類資訊包含的靜态常量,編譯之後就能确認
JVM 指令
invokedynamic JDK1.7新加入的一個虛拟機指令,相比于之前的四條指令,他們的分派邏輯都是固化在JVM内部,而invokedynamic則用于處理新的方法分派:它允許應用級别的代碼來确定執行哪一個方法調用,隻有在調用要執行的時候,才會進行這種判斷,進而達到動态語言的支援。(Invoke dynamic method)