Java中的常量池(字符串常量池、class常量池和運行時常量池)

轉載於:https://blog.csdn.net/qq_20641565/article/details/60332593

簡介:

這幾天在看Java虛擬機方面的知識時,看到了有幾種不同常量池的說法,然後我就去CSDN、博客園等上找資料,裏面說的內容真是百花齊放,各自爭豔,因此,我好好整理了一下,將我自認爲對的理解寫下來與大家共同探討:

在Java的內存分配中,總共3種常量池:

1.字符串常量池(String Constant Pool):

1.1:字符串常量池在Java內存區域的哪個位置?

  • 在JDK6.0及之前版本,字符串常量池是放在Perm Gen區(也就是方法區)中;
  • 在JDK7.0版本,字符串常量池被移到了堆中了。至於爲什麼移到堆內,大概是由於方法區的內存空間太小了。

1.2:字符串常量池是什麼?

  • 在HotSpot VM裏實現的string pool功能的是一個StringTable類,它是一個Hash表,默認值大小長度是1009;這個StringTable在每個HotSpot VM的實例只有一份,被所有的類共享。字符串常量由一個一個字符組成,放在了StringTable上。
  • 在JDK6.0中,StringTable的長度是固定的,長度就是1009,因此如果放入String Pool中的String非常多,就會造成hash衝突,導致鏈表過長,當調用String#intern()時會需要到鏈表上一個一個找,從而導致性能大幅度下降;
  • 在JDK7.0中,StringTable的長度可以通過參數指定:
-XX:StringTableSize=66666
  • 1

1.3:字符串常量池裏放的是什麼?

  • 在JDK6.0及之前版本中,String Pool裏放的都是字符串常量;
  • 在JDK7.0中,由於String#intern()發生了改變,因此String Pool中也可以存放放於堆內的字符串對象的引用。關於String在內存中的存儲和String#intern()方法的說明,可以參考我的另外一篇博客:

需要說明的是:字符串常量池中的字符串只存在一份! 
如:

String s1 = "hello,world!";
String s2 = "hello,world!";
  • 1
  • 2

即執行完第一行代碼後,常量池中已存在 “hello,world!”,那麼 s2不會在常量池中申請新的空間,而是直接把已存在的字符串內存地址返回給s2。(這裏具體的字符串如何分配就不細說了,可以看我的另一篇博客)

2.class常量池(Class Constant Pool):

2.1:class常量池簡介:

  • 我們寫的每一個Java類被編譯後,就會形成一份class文件;class文件中除了包含類的版本、字段、方法、接口等描述信息外,還有一項信息就是常量池(constant pool table),用於存放編譯器生成的各種字面量(Literal)和符號引用(Symbolic References);
  • 每個class文件都有一個class常量池。

2.2:什麼是字面量和符號引用:

  • 字面量包括:1.文本字符串 2.八種基本類型的值 3.被聲明爲final的常量等;
  • 符號引用包括:1.類和方法的全限定名 2.字段的名稱和描述符 3.方法的名稱和描述符。

3.運行時常量池(Runtime Constant Pool):

  • 運行時常量池存在於內存中,也就是class常量池被加載到內存之後的版本,不同之處是:它的字面量可以動態的添加(String#intern()),符號引用可以被解析爲直接引用
  • JVM在執行某個類的時候,必須經過加載、連接、初始化,而連接又包括驗證、準備、解析三個階段。而當類加載到內存中後,jvm就會將class常量池中的內容存放到運行時常量池中,由此可知,運行時常量池也是每個類都有一個。在解析階段,會把符號引用替換爲直接引用,解析的過程會去查詢字符串常量池,也就是我們上面所說的StringTable,以保證運行時常量池所引用的字符串與字符串常量池中是一致的。

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/zm13007310400/article/details/77534349

文章標籤: java常量池字符串

個人分類: jvm

相關熱詞: java《》 java的與 java‖和 java的和-- java的for

上一篇Java中字段、屬性、成員變量、局部變量、實例變量、靜態變量、類變量、常量

下一篇Java設置session失效時間

Java面向對象編程(高手養成記)

本課程主要講解JavaSE的發展歷史,JDK開發環境的搭建,面向對象編程、多線程、IO、類集、網絡、數據庫編程。

  • u013431095

    獄魔天使2018-06-27 13:38:39#4樓

    字符串常量池也是運行時常量池一部分

  • u013431095

    獄魔天使2018-06-27 13:31:49#3樓

    在JDK6.0及之前版本,字符串常量池是放在Perm Gen區(也就是方法區)中; perm gen的就是永久帶,在堆中實現的,爲了和堆區分,就別成爲非堆,然後方法區被拆分,類的數據信息移到了機器內存中,常量池則留在了堆中

  • jinsong1213

    全能碼農-ss2018-05-31 18:17:34#2樓

    字面量包括中的1 文本字符串是什麼? 和字符串常量池有什麼關係?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章