詳解Java String字符串對象的創建及管理(1)

http://developer.51cto.com/art/200810/91859.htm

Constant Pool常量池的概念:

在講到String的一些特殊情況時,總會提到String Pool或者Constant Pool,但是我想很多人都不太明白Constant Pool到底是個怎麼樣的東西,運行的時候存儲在哪裏,所以在這裏先說一下Constant Pool的內容。

String Pool是對應於在Constant Pool中存儲String常量的區域.習慣稱爲String Pool,也有人稱爲String Constant Pool.好像沒有正式的命名。

在java編譯好的class文件中,有個區域稱爲Constant Pool,他是一個由數組組成的表,類型爲cp_info constant_pool[],用來存儲程序中使用的各種常量,包括Class/String/Integer等各種基本Java數據類型。

對於Constant Pool,表的基本通用結構爲:

cp_info {
        u1 tag;
        u1 info[];
}

tag是一個數字,用來表示存儲的常量的類型,例如8表示String類型,5表示Long類型,info[]根據

類型碼tag的不同會發生相應變化。

對於String類型,表的結構爲:

CONSTANT_String_info {
        u1 tag;
        u2 string_index;
}

tag固定爲8,string_index是字符串內容信息,類型爲:

CONSTANT_Utf8_info {
        u1 tag;
        u2 length;
        u1 bytes[length];
}

tag固定爲1,length爲字符串的長度,bytes[length]爲字符串的內容。

(以下代碼在jdk6中編譯)

爲了詳細理解Constant Pool的結構,我們參看一些代碼:

String s1 = "sss111";
    String s2 = "sss222";
    System.out.println(s1 + " " + s2);

由於"sss111"和"sss222"都是字符串常量,在編譯期就已經創建好了存儲在class文件中。

在編譯後的class文件中會存在這2個常量的對應表示:

08 00 11 01 00 06 73 73 73 31 31 31 08 00 13 01 ; ......sss111....
00 06 73 73 73 32 32 32                         ; ..sss222

根據上面說的String常量結構,我們分析一下:

開始的08爲CONSTANT_String_info結構中的tag,而11應該是它的相對引用,01爲CONSTANT_Utf8_info的tag,06爲對應字符串的長度,73 73 73 31 31 31爲字符串對應的編碼,接着分析,會發現後面的是對應"sss222"的存儲結構。

經過上面分析,我們知道了11和13是兩個字符串的相對引用,就可以修改class文件來修改打印的內容,把class文件中的00 6E 00 04 00 03 00 00 00 24 12 10 4C 12 12 4D改成00 6E 00 04 00 03 00 00 00 24 12 10 4C 12 10 4D,程序就會輸出sss111 sss111,而不是和原程序一樣輸出sss111 sss222,因爲我們把對"sss222"的相對引用12改成了對"sss111"的相對引用10。

public class Test {
    public static void main(String[] args) {
        String s1 = "sss111";
        String s2 = "sss111";
    }
}

在上面程序中存在2個相同的常量"sss111",對於n個值相同的String常量,在Constant Pool中只會創建一個,所以在編譯好的class文件中,我們只能找到一個對"sss111"的表示:

000000abh: 08 00 11 01 00 06 73 73 73 31 31 31             ; ......sss111

在程序執行的時候,Constant Pool會儲存在Method Area,而不是heap中。

另外,對於""內容爲空的字符串常量,會創建一個長度爲0,內容爲空的字符串放到Constant Pool中,

而且Constant Pool在運行期是可以動態擴展的。

關於String類的說明

1.String使用private final char value[]來實現字符串的存儲,也就是說String對象創建之後,就不能再修改此對象中存儲的字符串內容,就是因爲如此,才說String類型是不可變的(immutable)。

2.String類有一個特殊的創建方法,就是使用""雙引號來創建.例如new String("i am")實際創建了2個String對象,一個是"i am"通過""雙引號創建的,另一個是通過new創建的.只不過他們創建的時期不同, 一個是編譯期,一個是運行期!

3.java對String類型重載了+操作符,可以直接使用+對兩個字符串進行連接。

4.運行期調用String類的intern()方法可以向String Pool中動態添加對象。



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