內存模型(堆和棧工作原理,String詳解)

   JVM主要管理兩種類型內存:堆和非堆。

1.堆是運行時數據區域,所有類實例和數組的內存均從此處分配,這些對象通過new、newarray、 anewarray和multianewarray等指令建立。堆由垃圾收集器來回收內存,它的優勢是可以動態分配內存大小,缺點就是存取較慢。

2.非堆就是堆之外的內存,它包括:

1)方法區

2)JVM內部處理或優化所需的內存(如 JITCompiler,Just-in-time Compiler,即時編譯後的代碼緩存)

3)類結構(如運行時常數池、字段和方法數據)

4)方法和構造方法的代碼

3.棧的優勢是,存取速度比堆要快,僅次於寄存器,棧數據可以共享。但缺點是,存在棧中的數據大小與生存期必須是確定的,缺乏靈活性。棧中主要存放一些基本類型的變量數據(int, short, long, byte, float, double, boolean, char)和對象句柄(引用)。

  String常量

1.一個String常量,它的值在常量池中(jvm爲每個被裝載的類型維護的一個有序集合)

2.常量池在內存中是以表的形式存在的,它用一個固定長度的字段來CONSTANT_String_info來存儲字符串的值(不存儲符號引用)。

3.所以當程序執行的時候,Method area中的常量池保存了很多String對象,它們可以被共享使用,不用每次在創建時都在堆中重新分配一塊內存,所能夠提高效率。

1)賦值

	String s1 = "abc";     
        //↑ 在字符串池創建了一個對象  
        String s2 = "abc";     
        //↑ 字符串pool已經存在對象“abc”(共享),所以創建0個對象,累計創建一個對象  
        System.out.println("s1 == s2 : "+(s1==s2));    
        //↑ true 指向同一個對象,  
        System.out.println("s1.equals(s2) : " + (s1.equals(s2)));    
2)new String(),通過new 創建的String對象會在堆中開闢兩塊內存

       String s3 = new String("abc");  
        //↑ 創建了兩個對象,一個存放在字符串池中,一個存在與堆區中;  
        //↑ 還有一個對象引用s3存放在棧中  
        String s4 = new String("abc");  
        //↑ 字符串池中已經存在“abc”對象,所以只在堆中創建了一個對象  
        System.out.println("s3 == s4 : "+(s3==s4));  
        //↑false   s3和s4棧區的地址不同,指向堆區的不同地址;  
        System.out.println("s3.equals(s4) : "+(s3.equals(s4)));  
        //↑true  s3和s4的值相同  
        System.out.println("s1 == s3 : "+(s1==s3));  
        //↑false 存放的地區多不同,一個棧區,一個堆區  
        System.out.println("s1.equals(s3) : "+(s1.equals(s3)));  
        //↑true  值相同  
3)字符串拼接,兩個字符串拼接,會產生新的對象

	String str6 = "b";  
        String str7 = "a" + str6;  
        String str67 = "ab";  
        System.out.println("str7 == str67 : "+ (str7 == str67));  
        //false ↑str6爲變量,在運行期纔會被解析。  
        final String str8 = "b";  
        String str9 = "a" + str8;  
        String str89 = "ab";  
        System.out.println("str9 == str89 : "+ (str9 == str89));  
        //true ↑str8爲常量變量,編譯期會被優化  
      
4)String.intern()
String的 intern()方法就是擴充常量池的 一個方法;當一個String實例str調用intern()方法時,Java 查找常量池中 是
有相同Unicode的字符串常量,如果有,則返回其的引用,如果沒有,則在常 量池中增加一個Unicode等於str的字
串並返回它的引用。
	
        String s0 = "你好"; 
        String s1 = new String("你好"); 
        String s2 = new String("你好"); 
        s1.intern(); //雖然執行了s1.intern(),但它的返回值沒有賦給s1,所以s1沒變
        s2 = s2.intern(); //把常量池中"你好"的引用賦給s2 
        System.out.println( s0 == s1); //flase
        System.out.println( s0 == s1.intern() ); //true//說明s1.intern()返回的是常量池中"你好"的引用
        System.out.println( s0 == s2 ); //true
		

發佈了26 篇原創文章 · 獲贊 29 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章