天天看點

JVM的class檔案結構詳解(二)

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種類型中的哪一個.

JVM的class檔案結構詳解(二)

以CONSTANT_Class_info常量為例,它的二維表示結構如下:

CONSTANT_Class_info表

JVM的class檔案結構詳解(二)
  • tag 表示目前常量的類型(目前常量為CONSTANT_Class_info,是以tag的值應為7,表一個類或接口的全限定名);
  • name_index 表示這個類或接口全限定名的位置.它的值表示指向常量池的第幾個常量.它會指向一個CONSTANT_Utf8_info類型的常量
JVM的class檔案結構詳解(二)

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的class檔案結構詳解(二)

類資訊包含的靜态常量,編譯之後就能确認

JVM的class檔案結構詳解(二)

JVM 指令

invokedynamic JDK1.7新加入的一個虛拟機指令,相比于之前的四條指令,他們的分派邏輯都是固化在JVM内部,而invokedynamic則用于處理新的方法分派:它允許應用級别的代碼來确定執行哪一個方法調用,隻有在調用要執行的時候,才會進行這種判斷,進而達到動态語言的支援。(Invoke dynamic method)