2012-04-18 104 views
49

我目前正在深入研究Java虛擬機的規範。我一直在閱讀Inside the JVM book online,有一個令人困惑的抽象,我似乎無法理解:常量池。這裏是該書的摘錄:Java常量池的用途是什麼?

對於加載的每種類型,Java虛擬機必須存儲常量池。常量池是類型使用的一組有序常量,包括文字(字符串,整數和浮點常量)以及對類型,字段和方法的符號引用。常量池中的條目由索引引用,非常類似於數組的元素。因爲它擁有對類型使用的所有類型,字段和方法的符號引用,所以常量池在Java程序的動態鏈接中起着核心作用

我對於上述和CP有一些疑問:

  1. CP是否位於.class文件中的每種類型?
  2. 作者用「符號參考」表示什麼?
  3. Constant Pool的目的是什麼?用簡單的英語?

回答

51

我覺得理解框架是如何使用圖來構建會有所幫助。

enter image description here

幀是其中操作數(操作指令)駐留而且那裏的動態鏈接發生。這是一種速記方式,可以這麼說,使用常量池來跟蹤班級和班級成員。

每個幀都包含對運行時常量池的引用。該引用指向正在爲該幀執行的方法的類的常量池。此引用有助於支持動態鏈接。

通常將C/C++代碼編譯爲目標文件,然後將多個目標文件鏈接在一起以產生可用的工件,如可執行文件或dll。在鏈接階段,每個目標文件中的符號引用被替換爲相對於最終可執行文件的實際內存地址。在Java中,這個鏈接階段是在運行時動態完成的。

編譯Java文件時,所有對變量和方法的引用都作爲符號引用存儲在類的常量池中。符號引用是邏輯引用,而不是實際指向物理內存位置的引用。

這是一個鏈接到James Blooms JVM Internals瞭解更多詳情。

+0

「當一個Java類被編譯...」?不是.class文件已經是已編譯的Java代碼嗎? – 2015-05-02 21:25:07

+1

是的,.java文件在編譯時變成.class文件。 – 2015-05-03 03:16:56

+0

鏈接被破壞 – 2016-02-23 01:30:14

6

常量池的目的是什麼,簡單的英語?

的CP是一個存儲器區域非常獨特的恆定值被存儲,以減少冗餘:

System.err.println("Hello"); 
System.out.println("Hello"); 

在CP只有在兩行中的一個字符串對象「你好」和編譯器的替代品相同的參考。您的.class文件只包含一個Hello字符串。 (其他類型相同)。

CP是否位於每個類型的.Class文件中?

是的,看看這裏:http://en.wikipedia.org/wiki/Java_class_file

+0

你將擴大多一點上也許是符號鏈接?我認爲這些是CP – Bober02 2012-04-18 13:20:01

63

常量池是.class文件(和它的內存中表示),它包含運行那個類的代碼所需要的常量的一部分。

這些常量包括程序員指定的文字和編譯器生成的符號引用。符號引用基本上是從代碼引用的類,方法和字段的名稱。 JVM使用這些引用將您的代碼鏈接到它所依賴的其他類。

例如,下面的代碼

System.out.println("Hello, world!"); 

產生以下的字節碼(javap輸出)

0: getstatic  #2; //Field java/lang/System.out:Ljava/io/PrintStream;    
3: ldc  #3; //String Hello, world!             
5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 

#n這裏是常量池中的引用。 #2System.out字段的符號引用,#3Hello, world!字符串,#4是對PrintStream.println(String)方法的符號引用。如您所見,符號引用不僅僅是名稱 - 例如,對該方法的符號引用還包含有關其參數(Ljava/lang/String;)和返回類型(V表示void)的信息。

您可以通過爲該類運行javap -verbose來檢查某個類的常量池。

+0

@ axtavt-哇的最重要的部分!很好的解釋。看起來像一個小錯字附近「#3是PrintStream的符號參考..」不應該是#4 – 2012-04-18 16:00:43

+0

@mashit:是的,修復。 – axtavt 2012-04-18 16:07:01

+0

但是「L」在「Ljava/lang/String」中的含義是什麼? ? – JackWM 2012-06-23 02:57:05

1

讓給實例首先要了解什麼字符串常量池的平均

public class StringConstantPool { 
     public static void main(String[] args) { 
      String s = "prasad"; 
      String s2 = "prasad"; 

      System.out.println(s.equals(s2)); 
      System.out.println(s == s2); 
     } 
    } 

輸出將是

true 

true 

這裏發生了什麼一步一步

1的類在調用JVM時加載。

2- JVM將查找程序中的所有字符串文字。

3-首先,它找到變量s它指的是字面「普拉薩德」,它會在內存中創建

4-甲用於字面「普拉薩德」參考將被放置在字符串常量池內存中。

-5-然後它找到另一個變量S2其指代相同的字符串文字「普拉薩德」

現在JVM已經發現字符串文字「普拉薩德」,二者變量s和S2港島線指代相同的對象即「普拉薩德」

enter image description here

我希望這是有幫助的

更多 http://www.journaldev.com/797/what-is-java-string-pool

+2

沒有'String constant pool'這樣的東西。在每個類文件中都有'常量池',並且存在JVM存在的字符串池的'字符串池'。 – Keenle 2015-03-02 14:06:54

+0

是的,在這裏我的意思是字符串池,謝謝你的評論 – 2015-03-02 14:16:52