JVM 記憶體模型:執行時常量池
1. 前言
最近研究Java基礎知識。發現Java執行時常量池和String字串有些一些細節的地方,值得我們注意的地方,最為一個Java開發人員對於這種java基本特性和JVM虛擬機器的記憶體模型我們需要去深入研究和掌握。
2. 執行時常量池
執行時常量池存在於方法區中,用於存放編譯期生成的各種字面量和符號引用。
2.1 String Pool
String Pool是執行時常量池中虛擬出來的一個概念。
Java中字串物件建立有兩種形式,一種為字面量形式,如String str = “droid”;,另一種就是使用new這種標準的構造物件的方法,如String str = new String(“droid”);,這兩種方式我們在程式碼編寫時都經常使用,尤其是字面量的方式。然而這兩種實現其實存在著一些效能和記憶體佔用的差別。這一切都是源於JVM為了減少字串物件的重複建立,其維護了一個特殊的記憶體,這段記憶體被成為字串常量池或者字串字面量池。
2.1.1 工作原理
當代碼中出現字面量形式建立字串物件時,JVM首先會對這個字面量進行檢查,如果字串常量池中存在相同內容的字串物件的引用,則將這個引用返回,否則新的字串物件被建立,然後將這個引用放入字串常量池,並返回該引用。
2.1.2 字面量建立形式
String str1 = "droid";
JVM檢測這個字面量,這裡我們認為沒有內容為droid的物件存在。JVM通過字串常量池查詢不到內容為droid的字串物件存在,那麼會建立這個字串物件,然後將剛建立的物件的引用放入到字串常量池中,並且將引用返回給變數str1。如果接下來有這樣一段程式碼
String str2 = "droid";
JVM還是要檢測這個字面量,JVM通過查詢字串常量池,發現內容為”droid”字串物件存在,於是將已經存在的字串物件的引用返回給變數str2。注意這裡不會重新建立新的字串物件。
2.1.3 使用new建立
String str3 = new String("droid");
當我們使用了new來構造字串物件的時候,不管字串常量池中有沒有相同內容的物件的引用,新的字串物件都會建立。因此我們使用下面程式碼測試一下,
String str4 = new String("droid");
System.out.println(str4 == str3);
結果如我們所想,為false,表明這兩個變數指向的為不同的物件。
2.1.4 intern
對於上面使用new建立的字串物件,如果想將這個物件的引用加入到字串常量池,可以使用intern方法。
呼叫intern後,首先檢查字串常量池中是否有該物件的引用,如果存在,則將這個引用返回給變數,否則將引用加入並返回給變數。
String str4 = str3.intern();
System.out.println(str4 == str1);
輸出的結果為true。
對於基礎型別的變數和常量:變數儲存在棧中,常量儲存在常量池中。
如以下程式碼:
int i1 = 9;
int i2 = 9;
int i3 = 9;
public static final int INT1 = 9;
public static final int INT2 = 9;
public static final int INT3 = 9;