經過Java字節碼發現有趣的內幕之String篇(一)

不少時候咱們在編寫Java代碼時,判斷和猜想代碼問題時主要是經過運行結果來獲得答案,本博文主要是想經過Java字節碼的方式來進一步求證咱們已知的東西。這裏沒有對Java字節碼知識進行介紹,若是想了解更多的Java字節碼或對其感興趣的朋友能夠先閱讀字節碼基礎:JVM字節碼初探html

String字面量能夠經過'=='判斷兩個字符串是否相同,是由於你們都知道'=='是用來判斷兩個對象的值引用地址是否一致,兩個值同樣的字符串字面量定義是否指向同一個值內存地址呢?答案是確定的。 java

package com.jaffa.test.string;

public class ConstPoolTest {
	public static void main(String[] args){
		String str1 = "strVal_1";
		String str2 = "strVal_1";
		//print str1==str2 is true
		System.out.printf("str1==str2 is %b",str1==str2);
	}
}

代碼中聲明瞭str1和str2的字面量值都爲strVal_1,而且打印出str1==str2爲true,說明兩個str1和str2變量同時指向同一個字符串常量值的內存地址,下面經過Java字節碼來驗證這個結果。 shell

在命令行咱們經過javap工具來查看一個class文件的字節碼。 工具

javap -v com.jaffa.test.string.ConstPoolTest

   

在Constant pool列表中看到#16爲一個String類型並值指向#17,而#17是一個utf8字符集編碼值爲strVal_1,因此#16和#17最終表達就是在常量池中有個String類型值爲strVal_1的常量數據。 編碼

那接下來須要確認str1和str2兩個變量值是否都是指向#16呢? .net

   

 //ldc表示將一個常量加載到操做數棧
 0: ldc           #16     //將#16對應的常量值加載到操做數棧中            
 2: astore_1              //將當前操做數棧中賦於變量1,即str1
 3: ldc           #16     //再次將#16對應的常量值加載到操做數棧中
 5: astore_2              //將當前操做數棧中賦於變量2,即str2

從上面字節碼執行來看,str1和str2都是被賦於同一個常量值,由此能夠得出兩個變動指向同一個內存地址。 命令行

經過一樣的方式,咱們來看一下若是是非字面量的狀況會是怎麼樣的,Java代碼以下: code

package com.jaffa.test.string;

public class ConstPoolTest {
	public static void main(String[] args){
		String str1 = "strVal_1";
		String str2 = new String("strVal_1");
		
		System.out.printf("str1==str2 is %b",str1==str2);
	}
}

上面代碼輸出結果爲false,經過javap查看發現str2變量的字節碼指令發生了變化,以下現兩截圖: htm

     

   

 //ldc表示將一個常量加載到操做數棧
 0: ldc           #16     //將#16對應的常量值加載到操做數棧中            
 2: astore_1              //將當前操做數棧中賦於變量1,即str1
 3: new           #18     //建立了一個類實例,#18指向一個實例類型String
 6: dup                   //配合上行完成棧值複製操做指令,將new從新壓入棧頂
 7: ldc           #16     //將#16對應的常量值加載到操做數棧中 
 9: invokespecial #20     //調用String實例初始化方法,並將#16輸入
12: astore_2              //將new出來的實例賦於變量2,即str2

這時str2變量是建立一個新的內存地址,而非直接指向#16常量內存地址,因此str1==str2的結果爲false。同時能夠看到經過new String()帶來看更多的字節碼指令操做,運行上花費了更多的系統資源。 對象

下篇:將經過字節碼發現String操做內幕

相關文章
相關標籤/搜索