String 內存分配

看了好多文章,網上大多數文章寫的不是很詳細,結合很多文章之後,寫下自己的理解


從一個例子開始

String s = new String( "myString" );

其中字符串常量是”myString”,在編譯時被存儲在常量池(常量池在方法區)的某個位置。在解析階段,虛擬機發現字符串常量”myString”,它會在一個內部字符串常量列表中查找,如果沒有找到,那麼會在裏面創建一個包含字符序列[myString]的String對象s1,然後把這個字符序列和對應的String對象作爲名值對( [myString], s1 )保存到內部字符串常量列表中(內部字符串常量列表存在string pool中,其實現是StringTable類)。然後執行new String 在堆裏面創建一個對象,其包含字符串序列[myString],然後返回其地址給棧中的s。也就是說,這裏創建了兩個對象,一個是指向常量池中的s1,第二個是堆中的new出來的對象。

如果虛擬機後面又發現了一個相同的字符串常量myString,它會在這個內部字符串常量列表內找到相同的字符序列,然後返回對應的String對象的引用。維護這個內部列表的關鍵是任何特定的字符序列在這個列表上只出現一次。

例如
String s2 = "myString"
運行時s2會從內部字符串常量列表內得到s1的返回值,所以s2和s1都指向同一個String對象。但是String對象s在堆裏的一個不同位置,所以和s1不相同。

JAVA中的字符串常量可以作爲String對象使用,字符串常量的字符序列本身是存放在常量池中,在字符串內部列表中每個字符串常量的字符序列對應一個String對象,實際使用的就是這個對象。

2.字符串截留intern

在某些上下文環境下,僅僅保留某個字符串的一份copy能夠提高內存的使用和效率。String類的intern()方法可以截留字符串,如果String對象包含的字符序列不在字符串常量內部列表中,那麼就把這個String對象包含的字符序列和String對象的引用作爲名值對保存到內部列表中,最後intern()返回一個指向String對象本身的引用;如果 String對象包含的字符序列在字符串常量內部列表中,那麼就返回列表的名值對中的對應的字符串對象引用,而String對象本身的就會被丟棄。

例如,s.intern()就會返回和s2相同的引用,而以前的s對象就會被垃圾回收。

使用intern()要注意,被放到字符串內部列表中的字符串對象是不會被垃圾回收的,生命週期和整個程序相同,所以如果使用不當會造成內存泄露。

內容大部分取自 http://blog.csdn.net/sureyonder/article/details/5569366 再加上自己理解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章