Java中字串記憶體位置淺析

Code小天發表於2018-03-16

前言

之前寫過一篇關於JVM記憶體區域劃分的文章,但是後來被問到Java裡面String存放的位置,之前只記得String是一個不變的量,應該是要存放在常量池裡面的,但是後來問到new一個String出來應該是放到哪裡的,這個應該是放到堆裡面的,後來又問到String的引用是放在什麼地方的,這些還不是很清楚,現在總結一下:基本型別的變數資料和物件的引用都是放在棧裡面的,物件本身放在堆裡面,顯式的String常量放在常量池,String物件放在堆中。

常量池的說明

常量池之前是放在方法區裡面的,也就是在永久代裡面的,從JDK7開始移到了堆裡面。這一改變我們可以從oracle的release version的notes裡的** Important RFEs Addressed in JDK 7 **看到。

Area: HotSpot
Synopsis: In JDK 7, interned strings are no longer allocated in the permanent 
generation of the Java heap, but are instead allocated in the main part of the 
Java heap (known as the young and old generations), along with the other 
objects created by the application. This change will result in more data 
residing in the main Java heap, and less data in the permanent generation, and 
thus may require heap sizes to be adjusted. Most applications will see only 
relatively small differences in heap usage due to this change, but larger 
applications that load many classes or make heavy use of the String.intern() 
method will see more significant differences.
RFE: 6962931
複製程式碼

String記憶體位置說明

1.顯式的String常量

String a = "holten";
String b = "holten";
複製程式碼
  • 第一句程式碼執行後就在常量池中建立了一個值為holten的String物件;
  • 第二句執行時,因為常量池中存在holten所以就不再建立新的String物件了。
  • 此時該字串的引用在虛擬機器棧裡面。

2.String物件

String a = new String("holtenObj");
String b = new String("holtenObj");
複製程式碼
  • Class被載入時就在常量池中建立了一個值為holtenObj的String物件,第一句執行時會在堆裡建立new String("holtenObj")物件;
  • 第二句執行時,因為常量池中存在holtenObj所以就不再建立新的String物件了,直接在堆裡建立new String("holtenObj")物件。

驗證一下

/**
 * Created by holten.gao on 2016/8/16.
 */
public class Main {
    public static void main(String[] args){
        String str1 = "高小天";
        String str2 = "高小天";
        System.out.println(str1==str2);//true
        
        String str3 = new String("高大天");
        String str4 = new String("高大天");
        System.out.println(str3==str4);//false
    }
}
複製程式碼

返回結果:

true
false
複製程式碼

微信掃描下方二維碼,關注公眾號,檢視獲取更多文章

二維碼

相關文章