天天看點

JVM 記憶體模型:運作時常量池1. 前言2. 運作時常量池

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 字面量建立形式

JVM檢測這個字面量,這裡我們認為沒有内容為droid的對象存在。JVM通過字元串常量池查找不到内容為droid的字元串對象存在,那麼會建立這個字元串對象,然後将剛建立的對象的引用放入到字元串常量池中,并且将引用傳回給變量str1。如果接下來有這樣一段代碼

JVM還是要檢測這個字面量,JVM通過查找字元串常量池,發現内容為”droid”字元串對象存在,于是将已經存在的字元串對象的引用傳回給變量str2。注意這裡不會重新建立新的字元串對象。

2.1.3 使用new建立

當我們使用了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;
           

繼續閱讀