java String 比較問題及jvm記憶體模型
總是被java字串問題給困擾,今天總結一下:
看如下程式碼:
public class Main{
public static void main(String[] args) {
String i = "abc";
String j = "abc";
String k = new String("abc");
if (i == j){
System.out.println("true");
}
else {
System.out.println("false");
}
}
}
1、i == j : 列印true
2、i == k : 列印false
用一張圖來解釋上面的結果:
物件引用
1、i,j,k都是存在棧中的,i和k中存放的是指向執行時常量池中的“abc”的記憶體地址(所以i==k);j中存的是指向堆中“abc”的地址所以(i != j)。
2、“==”比較的是棧中變數值的大小(引用資料型別比較的是記憶體地址,基本資料型別比較的是值),而equals(String對equals進行了重寫)比較的是存在堆中或者常量池中的值。
說明:
1.方法區:
是各個執行緒共享的記憶體區域,它用於儲存class二進位制檔案,包含了虛擬機器載入的類資訊、常量、靜態變數、即時編譯後的代 碼等資料。它有個名字叫做Non-Heap(非堆),目的是與Java堆區分開。
- 常量池:
存放字串常量和基本型別常量(public static final)。
- 靜態域:
位於方法區的一塊記憶體。存放類中以static宣告的靜態成員變數
2、JVM堆(Java Heap):
Java 堆也是屬於執行緒共享的記憶體區域,它在虛擬機器啟動時建立,是Java 虛擬機器所管理的記憶體中最大的一塊,主要用於存放物件例項,幾乎所有的物件例項都在這裡分配記憶體,注意Java 堆是垃圾收集器管理的主要區域,因此很多時候也被稱做GC 堆,如果在堆中沒有記憶體完成例項分配,並且堆也無法再擴充套件時,將會丟擲OutOfMemoryError 異常。
3、程式計數器(Program Counter Register):
屬於執行緒私有的資料區域,是一小塊記憶體空間,主要代表當前執行緒所執行的位元組碼行號指示器。位元組碼直譯器工作時,通過改變這個計數器的值來選取下一條需要執行的位元組碼指令,分支、迴圈、跳轉、異常處理、執行緒恢復等基礎功能都需要依賴這個計數器來完成。
4、虛擬機器棧(Java Virtual Machine Stacks):
屬於執行緒私有的資料區域,與執行緒同時建立,總數與執行緒關聯,代表Java方法執行的記憶體模型。每個方法執行時都會建立一個棧楨來儲存方法的的變量表、運算元棧、動態連結方法、返回值、返回地址等資訊。每個方法從呼叫直結束就對於一個棧楨在虛擬機器棧中的入棧和出棧過程,如下(圖有誤,應該為棧楨):
5、本地方法棧(Native Method Stacks):
本地方法棧屬於執行緒私有的資料區域,這部分主要與虛擬機器用到的 Native 方法相關,一般情況下,我們無需關心此區域。
參考部落格: