JVM中的常量池簡介

    1.簡介

    編譯.java文件時,會得到一個擴展名為.class的單獨的類文件。 .class文件由幾個部分組成,並且常量池就是其中之一。

    在本快速教程中,我們將探討常量池的詳細信息。另外,我們將看到它支持什麼類型以及如何格式化信息。

    2. Java中的常量池

    簡而言之,常量池包含運行特定類的代碼所需的常量。基本上,它是類似於符號表的運行時數據結構。它是Java類文件中每個類或每個接口的運行時表示形式。

    常量池的內容由編譯器生成的符號引用組成。這些引用是從代碼引用的變量,方法,接口和類的名稱。 JVM使用它們將代碼與它其他依賴的類鏈接。

    讓我們使用一個簡單的Java類來了解常量池的結構:

    public class ConstantPool {
    
    
    
     public void sayHello() {
    
     System.out.println("Hello World");
    
     }
    
     }

    要查看常量池的內容,我們需要首先編譯文件,然後運行以下命令:

    javap -v name.class

    上面的命令將產生:

     #1 = Methodref #6.#14 // java/lang/Object."<init>":()V
    
     #2 = Fieldref #15.#16 // java/lang/System.out:Ljava/io/PrintStream;
    
     #3 = String #17 // Hello World
    
     #4 = Methodref #18.#19 // java/io/PrintStream.println:(Ljava/lang/String;)V
    
     #5 = Class #20 // com/baeldung/jvm/ConstantPool
    
     #6 = Class #21 // java/lang/Object
    
     #7 = Utf8 <init>
    
     #8 = Utf8 ()V
    
     #9 = Utf8 Code
    
     #10 = Utf8 LineNumberTable
    
     #11 = Utf8 sayHello
    
     #12 = Utf8 SourceFile
    
     #13 = Utf8 ConstantPool.java
    
     #14 = NameAndType #7:#8 // "<init>":()V
    
     #15 = Class #22 // java/lang/System
    
     #16 = NameAndType #23:#24 // out:Ljava/io/PrintStream;
    
     #17 = Utf8 Hello World
    
     #18 = Class #25 // java/io/PrintStream
    
     #19 = NameAndType #26:#27 // println:(Ljava/lang/String;)V
    
     #20 = Utf8 com/baeldung/jvm/ConstantPool
    
     #21 = Utf8 java/lang/Object
    
     #22 = Utf8 java/lang/System
    
     #23 = Utf8 out
    
     #24 = Utf8 Ljava/io/PrintStream;
    
     #25 = Utf8 java/io/PrintStream
    
     #26 = Utf8 println
    
     #27 = Utf8 (Ljava/lang/String;)V
    

    #n表示對常量池的引用。 #17是對“Hello World” String的符號引用,#18是System.out ,而#19是println.同樣, #8強調方法的返回類型為void而#20為完全限定的類名。

    重要的是要注意,常量池表從索引1開始。索引值0被視為無效索引。

    2.1。種類

    常量池支持幾種類型:

    • IntegerFloat :具有32位常量
    • DoubleLong :具有64位常量
    • String :一個16位的字符串常量,指向池中包含實際字節的另一個條目
    • Class :包含完全限定的類名稱
    • Utf8 :字節流
    • NameAndType :冒號分隔的一對值,第一個條目表示名稱,第二個條目表示類型
    • FieldrefMethodrefInterfaceMethodref :點分隔的一對值,第一個值指向Class條目,而第二個值指向NameAndType條目

    那麼其他類型如booleanshortbyte呢?這些類型在池中表示為Integer常量。

    2.2。格式

    表中的每個條目均遵循通用格式:

    cp_info {
    
     u1 tag;
    
     u1 info[];
    
     }

    最初的1字節標籤指示常量的種類。 JVM抓取並攔截標籤後,便知道標籤後面的內容。通常,標籤後跟兩個或多個字節,以攜帶有關該常數的信息。

    讓我們看一些類型及其標籤索引:

    • Utf8 :1
    • Integer :3
    • Float :4
    • Long :5
    • Double :6
    • 班級參考:7
    • String參考:8

    只有在JVM完成加載後,才會創建任何類或接口的常量池。

    3.結論

    在這篇快速文章中,我們了解了JVM中的常量池。我們已經看到它包含用於定位實際對象的符號引用。此外,我們還將研究常量池如何查看常量池的內容及其類型的信息。