本文轉載自運行時常量池
運行時常量池( Runtime Constant Pool)是每一個類或接口的常量池( Constant_Pool)的運行時表示形式。
它包括了若干種不同的常量:從編譯期可知的數值字面量到必須運行期解析后才能獲得的方法或字段引用。運行時常量池扮演了類似傳統語言中符號表( SymbolTable)的角色,不過它存儲數據范圍比通常意義上的符號表要更為廣泛。
每一個運行時常量池都分配在 Java 虛擬機的方法區之中,在類和接口被加載到虛擬機后,對應的運行時常量池就被創建出來。
以上,是Java虛擬機規范中關於運行時常量池的定義。
運行時常量池在JDK各個版本中的實現
根據Java虛擬機規范約定:每一個運行時常量池都在Java虛擬機的方法區中分配,在加載類和接口到虛擬機后,就創建對應的運行時常量池。
在不同版本的JDK中,運行時常量池所處的位置也不一樣。以HotSpot為例:
在JDK 1.7之前,方法區位於堆內存的永久代中,運行時常量池作為方法區的一部分,也處於永久代中。
因為使用永久代實現方法區可能導致內存泄露問題,所以,從JDK1.7開始,JVM嘗試解決這一問題,在1.7中,將原本位於永久代中的運行時常量池移動到堆內存中。(永久代在JDK 1.7並沒有完全移除,只是原來方法區中的運行時常量池、類的靜態變量等移動到了堆內存中。)
在JDK 1.8中,徹底移除了永久代,方法區通過元空間的方式實現。隨之,運行時常量池也在元空間中實現。
運行時常量池中常量的來源
運行時常量池中包含了若干種不同的常量:
編譯期可知的字面量和符號引用(來自Class常量池) 運行期解析后可獲得的常量(如String的intern方法)
所以,運行時常量池中的內容包含:Class常量池中的常量、字符串常量池中的內容
運行時常量池、Class常量池、字符串常量池的區別與聯系
虛擬機啟動過程中,會將各個Class文件中的常量池載入到運行時常量池中。
所以, Class常量池只是一個媒介場所。在JVM真的運行時,需要把常量池中的常量加載到內存中,進入到運行時常量池。
字符串常量池可以理解為運行時常量池分出來的部分。加載時,對於class的靜態常量池,如果字符串會被裝到字符串常量池中。