JVM記憶體模型
- 1、JVM運作時資料區分布圖
-
-
-
- 1.1、線程共享資料區:方法區(靜态變量)、堆(所有數組和對象都是在堆中産生的)
- 1.2、線程隔離資料區:Java虛拟機棧、本地方法棧(java虛拟機需要調用本地方法庫)、程式計數器(主要是用來記錄位元組指令的行号)。這三塊記憶體是線程私有的,生命周期和線程的生命周期是一樣的
-
-
- 2、JVM記憶體模型之程式電腦
- 3、JVM記憶體模型之java虛拟機棧
- 4、JVM記憶體模型之本地方法棧(Native Method Stack)
- 5、JVM記憶體模型之JAVA堆
- 6、JVM記憶體模型之方法區
- 7、JVM記憶體模型之方法區運作時常量池
1、JVM運作時資料區分布圖
1.1、線程共享資料區:方法區(靜态變量)、堆(所有數組和對象都是在堆中産生的)
1.2、線程隔離資料區:Java虛拟機棧、本地方法棧(java虛拟機需要調用本地方法庫)、程式計數器(主要是用來記錄位元組指令的行号)。這三塊記憶體是線程私有的,生命周期和線程的生命周期是一樣的

2、JVM記憶體模型之程式電腦
- 是什麼?
- 程式計數器是一塊較小的記憶體空間,它可以看作是目前線程所執行的位元組碼的行号訓示器
- 線程是一個獨立的執行單元,是由CPU控制執行的
- 位元組碼解釋器工作時就是通過改變這個計數器的值來選取下一條需要執行的位元組碼指令,分支、循環、跳轉、異常處理、線程恢複等基礎功能都需要依賴這個計數器來完成
- 為什麼?
- 為了線程切換後能恢複到正确的執行位置,每條線程都需要有一個獨立的程式計數器,各條線程之間計數器互不影響,獨立存儲,我們稱這類記憶體區域為“線程私有”的記憶體
- 特點?
- 記憶體區域中唯一一 個沒有規定任何 OutOfMemoryError 情況的區域
3、JVM記憶體模型之java虛拟機棧
- 是什麼?
- 用于作用于方法執行的一塊Java記憶體區域(即在方法執行時會建立一塊記憶體區域)
public class A {
public static void a(){
System.out.println("enter method a");
}
public static void b(){
a();
System.out.println("enter method b");
}
public static void main(String[] args) {
b();
}
}
- 為什麼?
- 每個方法在執行的同時都會建立一個棧幀(Stack Framel)用于存儲局部變量表、操作數棧(例如 int c=a+b)、動态連結(對對象引用的位址)、方法出口(return的值)等資訊。每一個方法從調用直至執行完成的過程,就對應着一個棧幀在虛拟機棧中入棧到出棧的過程
- 特點?
- 局部變量表存放了編譯期可知的各種基本資料類型(boolean、byte、char、short、int、float、long、double)以及對象引用(reference 類型)
- 如果線程請求的棧深度大于虛拟機所允許的深度,将抛出 StackOverflowError 異常
public class A {
//進行遞歸調用
public static void b(){
b();
System.out.println("enter method b");
}
public static void main(String[] args) {
b();
}
}
4、JVM記憶體模型之本地方法棧(Native Method Stack)
- 是什麼?
- 用于作用域本地方法執行的一塊Java記憶體區域
- 什麼是本地方法?
- 為什麼?
- 與Java虛拟機棧相同,每個方法在執行的同時都會建立一個棧幀(Stack Framel)用于存儲局部變量表、操作數棧、動态連結、方法出口等資訊。每一個方法從調用直至執行完成的過程,就對應着一個棧幀在虛拟機棧中入棧到出棧的過程
- 特點?
- Hotshot将Java虛拟機棧和本地方法棧合二為一
import java.util.concurrent.atomic.AtomicInteger;
public class A {
//native方法沒有方法體,是調用cpu原子指令的方法,調用其他語言
public native static void c();
public static void a(){
System.out.println("enter method a");
}
public static void b(){
a();
System.out.println("enter method b");
}
public static void main(String[] args) {
b();
System.out.println("enter method main");
//CAS是一條CPU的原子指令
AtomicInteger atomicInteger = new AtomicInteger(1);
//當是1的時候更新為2
atomicInteger.compareAndSet(1,2);
}
}
5、JVM記憶體模型之JAVA堆
- 是什麼?
- 是Java記憶體區域中一塊用來存放對象執行個體的區域,【幾乎所有的對象執行個體都在這裡配置設定記憶體】
- 為什麼?
- 此記憶體區域的唯一目的就是存放對象執行個體
- Java 堆(Java Heap)是 Java 虛拟機所管理的記憶體中最大的一塊 Java 堆是被所有線程共享的一塊記憶體區域
- 特點?
- Java 堆是垃圾收集器管理的主要區域,是以很多時候也被稱做“GC 堆”(Garbage
- -Xmx -Xms
- Java堆可以分成新生代和老年代 新生代可分為To Space、From Space、Eden
根據程序id(pid)檢視堆。sudo jmap -heap pid
6、JVM記憶體模型之方法區
- 是什麼?
- 是各個線程共享的記憶體區域,它用于存儲已被虛拟機加載的類資訊、常量、靜态變量、即時編譯器編譯後的代碼等資料
- 什麼是類資訊:類版本号、方法、接口
- 為什麼?
- 記憶體中存放類資訊、靜态變量等資料,屬于線程共享的一塊區域
- Hotspot使用永久代(垃圾回收GC裡面的一個區域)來實作方法區,Hotspot為了像Java堆一樣管理這部分記憶體是以将永久代放在方法區中,通過垃圾回收器來管理這一部分記憶體 (JRockit、IBM J9VM沒有永久代的概念)
- 特點?
- 并非資料進入了方法區就如永久代的名字一樣“永久”存在了。這區域的記憶體回收目标主要是針對常量池的回收和對類型的解除安裝
- 方法區也會抛出OutofMemoryError,當它無法滿足記憶體配置設定需求時
7、JVM記憶體模型之方法區運作時常量池
- 是什麼?
- 運作時常量池是方法區的一部分,Class檔案除了有類的版本、字段、方法、接口等描述資訊外,還有一項資訊是常量池,用于存放編譯器生成的各種字面量和符号引用,這部分内容将在類加載後進入方法區的運作時常量池中存放。
- 運作時常量池的模拟
- 特點:
- 運作時常量池是方法區的一部分,受到方法區記憶體的限制,當常量池再申請到記憶體時會抛出OutOfMemoryError異常
public class A {
public static void main(String[] args) {
String a = "abc";//存在方法區
String b = "abc";//存在方法區
System.out.println(a==b);//true
String c = new String("abc");//存在堆中
System.out.println(a==c);//false
System.out.println(a==c.intern());//true将c移到堆中
}
}