JDK1.8關於運行時常量池, 字符串常量池的要點


JDK1.8關於運行時常量池, 字符串常量池的要點

網上關於jdk 1.8的各種實驗, 結論魚龍混雜 , 很多都相矛盾,網上有的實驗也被后人測試出了不同的結果

很多都分辨不了真假, 這里記錄一下網絡上正確的結論, 歡迎指正!

首先自行區分運行時常量池與Class文件常量池(靜態常量池)的概念, JVM內存模型 ,方法區與永久代的區別, 有些在我的其他博客有介紹, 連接在文尾

在JDK1.7之前運行時常量池邏輯包含字符串常量池存放在方法區, 此時hotspot虛擬機對方法區的實現為永久代

在JDK1.7 字符串常量池被從方法區拿到了堆中, 這里沒有提到運行時常量池,也就是說字符串常量池被單獨拿到堆,運行時常量池剩下的東西還在方法區, 也就是hotspot中的永久代

在JDK1.8 hotspot移除了永久代用元空間(Metaspace)取而代之, 這時候字符串常量池還在堆, 運行時常量池還在方法區, 只不過方法區的實現從永久代變成了元空間(Metaspace)

對於直接做+運算的兩個字符串(字面量)常量,並不會放入字符串常量池中,而是直接把運算后的結果放入字符串常量池中
(String s = "abc"+ "def", 會直接生成“abcdef"字符串常量 而不把 "abc" "def"放進常量池)
對於先聲明的字符串字面量常量,會放入字符串常量池,但是若使用字面量的引用進行運算就不會把運算后的結果放入字符串常量池中了
(String s = new String("abc") + new String("def"),在構造過程中不會生成“abcdef"字符串常量)
總結一下就是JVM會對字符串常量的運算進行優化,未聲明的,只放結果;已經聲明的,只放聲明
常量池中同時存在字符串常量和字符串引用。直接賦值和用字符串調用String構造函數都可能導致常量池中生成字符串常量;而intern()方法會嘗試將堆中對象的引用放入常量池

String str1 = "a";
String str2 = "b";
String str4 = str1 + str2; //該語句只在堆中生成一個對象(str4)
這句被Java編譯器做了優化, 實際上使用StringBuilder實現的(不在堆里生成str1和str2對象)

String str5 = new String("ab");(字符串常量池中不存在"ab"時)在字符換常量池中創建"ab"對象,在堆中生成了一個對象str5, str5指向堆上new的對象,而str5內部的char value[]則指向常量池中的char value[]
關於這個問題可以參考這篇博客:new String()究竟創建幾個對象?

附上自己相關的幾篇博客:

永久代->元空間 https://blog.csdn.net/q5706503/article/details/84621210

string.intern https://blog.csdn.net/q5706503/article/details/84586219

JVM內存空間模型 https://blog.csdn.net/q5706503/article/details/84614158
————————————————
版權聲明:本文為CSDN博主「NO0b」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/q5706503/article/details/84640762


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM