常量池在JVM中分為三種:字符串常量池,運行時常量池,Class常量池
討論范圍 JDK 1.7版本及以后
字符串常量池(String pool)
(1)什么是字符串常量池?
①字符串常量由一個個字符組成。在HotSpot虛擬機中,字符串常量池是有一個名為 StringTable 的類來實現的,StringTable是一個哈希表HashSet<String>,默認長度為1009,是被所有類共享的,因此在JVM中的實例只有一份。注意它只存儲對java.lang.String實例的引用,而不存儲String對象的內容,根據這個引用可以得到具體的String對象。一般我們說一個字符串進入了全局的字符串常量池其實是說在這個StringTable中保存了對它的引用,反之,如果說沒有在其中就是說StringTable中沒有對它的引用。
②在JDK1.6版本中,StringTable的長度是固定的,長度就是1009。因此如果保存的字符串常量過多,就會造成哈希沖突,導致鏈表過長,而鏈表過長的直接影響就是 當調用String.intern時性能會大幅下降(因為要一個一個找)。
③在JDK1.7版本中,StringTable的長度可以通過參數來指定:-XX:StringTableSize=123456
(2)字符串常量池保存在JVM哪個區域?
在JDK1.6及之前的版本中,字符串常量池是放在永久代(Perm Gen)中,確切來講是永久代的方法區中。
在JDK1.7后的版本中,字符串常量池就被移到了堆(Heap)中。之所以會被移到堆中,可能是方法區的內存空間太小了。
(3)字符串常量池中保存的是什么?
字符串常量池只存儲引用,不存儲內容!字符串不是存在字符串常量池中而是存在堆內存中,字符串池中只是該字符串的引用。
規范里把存儲Java對象的地方定義為Java heap,其它地方是不會存有Java對象的實體的(有的話那根據定于也要算Java heap的一部分)
注:在字符串常量池中的字符串只能存在一份。
String s1 ="JVM";
String s2 ="JVM";
//執行完第一段代碼后,由于常量池中已經存在了"JVM"這個字符串的引用,
//所以s2不會在常量池中申請新的空間,而是直接把已存在的字符串內存地址返回給s2。
Class常量池
(1)什么是Class常量池?
①在每一個Java類被編譯后,會形成一個class文件。Class文件除了有類信息,字段,方法,接口等描述信息,還有一項信息是常量池(Constant Pool Table),每一個class文件都有一個class常量池。
(2)Class常量池保存在JVM哪個區域?
保存在堆中。
(3)Class常量池中保存的是什么?
用于存放編譯器生成的各種字面量(Literal)和符號引用(Symbolic References);
字面量(Literal)包括:文本字符串,八種基本類型的值,被聲明為final的常量等
符號引用(Symbolic References)包括:類和接口的全限定名(Full Qualified Name),字段的名稱和描述符(Descriptor),方法的名稱和描述符
運行時常量池(Runtime Constant Pool)
(1)什么是運行時常量池?
運行時常量池,則是jvm虛擬機在完成類裝載操作后,將class文件中的常量池載入到內存中,并保存在方法區中。 運行時常量池也就是class常量池被加載到內存之后的版本,因為每一個class文件都有一個class常量池,因此運行時常量池也是每個類都有一個。我們常說的常量池,就是指方法區中的運行時常量池。
運行時常量池相對于Class文件常量池的重要特征是具有動態性。除了在編譯器產生的常量可以進入運行時常量池外,還可以在運行期間將新的常量放入池中,比如String 的 intern方法。
(2)運行時常量池保存在JVM哪個區域?
位于方法區,Java虛擬機規范中將方法區描述為堆的邏輯部分,所以實際上還是在堆中。
(3)Class常量池中保存的是什么?
方法區的一部分。Class文件中除了有類的版本、字段、方法、接口等描述信息外,還有常量池(Constant Pool Table),存放編譯期生成的各種字面量和符號引用,這部分內容將在類加載后進入方法區的運行時常量池。也就是說運行時常量池是class常量池的另一個版本。
但是,這個“進入”過程,并不會直接把所有類中定義的常量全部都加載進來,而是會做個比較,如果需要加到字符串常量池中的字符串已經存在,那么就不需要再把字符串字面量加載進來了。
推薦閱讀
https://www.zhihu.com/question/29884421
https://www.zhihu.com/question/57109429/answer/151717241
https://www.zhihu.com/question/55994121/answer/147296098
https://blog.csdn.net/zm13007310400/article/details/77534349