? 作者:小胡_不糊涂
🌱 作者主頁:小胡_不糊涂的個人主頁
📀 收錄專欄:JavaEE
💖 持續更文,關注博主少走彎路,謝謝大家支持 💖
JVM
- 1. 運行流程
- 2. 運行時數據區
- 2.1 堆(線程共享)
- 2.2 Java虛擬機棧(線程私有)
- 2.3 本地方法棧(線程私有)
- 2.4 程序計數器(線程私有)
- 2.5 方法區(線程共享)
- 3. 數據內存區域劃分
JVM 是 Java Virtual Machine 的簡稱,意為 Java虛擬機。
虛擬機是指通過軟件模擬的具有完整硬件功能的、運?在?個完全隔離的環境中的完整計算機系統。
1. 運行流程
程序在執?之前先要把java代碼轉換成字節碼(class?件),JVM ?先需要把字節碼通過?定的?式–
類加載器(ClassLoader),把?件加載到內存中運?時數據區(Runtime Data Area),?字節碼?件是 JVM 的?套指令集規范,并不能直接交個底層操作系統去執?,因此需要特定的命令解析器執?引擎(Execution Engine),將字節碼翻譯成底層系統指令再交由CPU去執?,?這個過程中需要調?其他語?的接?**本地庫接?(Native Interface)**來實現整個程序的功能,這就是這4個主要組成部分的職責與功能。
JVM 主要通過分為以下 4 個部分,來執? Java 程序的,它們分別是:
- 類加載器(ClassLoader)
- 運?時數據區(Runtime Data Area)
- 執?引擎(Execution Engine)
- 本地庫接?(Native Interface)
2. 運行時數據區
JVM 運?時數據區域也叫內存布局,但需要注意的是它和 Java 內存模型((Java Memory Model,簡稱 JMM)完全不同,屬于完全不同的兩個概念,它由以下 5 ?部分組成:
2.1 堆(線程共享)
**堆的作?:**程序中創建的所有對象都在保存在堆中。
堆??分為兩個區域:新?代和??代,新?代放新建的對象,當經過?定 GC 次數之后還存活的對象會放???代。新?代還有 3 個區域:?個 Endn + 兩個 Survivor(S0/S1)。
垃圾回收的時候會將 Endn 中存活的對象放到?個未使?的 Survivor 中,并把當前的 Endn 和正在使?的 Survivor 清楚掉。
2.2 Java虛擬機棧(線程私有)
Java 虛擬機棧的作?: Java 虛擬機棧的?命周期和線程相同,Java 虛擬機棧描述的是 Java ?法執?的內存模型:每個?法在執?的同時都會創建?個棧幀(Stack Frame)?于存儲局部變量表、操作數棧、動態鏈接、?法出?等信息。
堆內存、棧內存中,棧內存指的就是虛擬機棧。
Java 虛擬機棧中包含了以下 4 部分:
- 局部變量表: 存放了編譯器可知的各種基本數據類型(8?基本數據類型)、對象引?。局部變量表所需的內存空間在編譯期間完成分配,當進??個?法時,這個?法需要在幀中分配多?的局部變量空間是完全確定的,在執?期間不會改變局部變量表??。簡單來說就是存放?法參數和局部變量。
- 操作棧:每個?法會?成?個先進后出的操作棧。
- 動態鏈接:指向運?時常量池的?法引?。
- ?法返回地址:PC 寄存器的地址。
線程私有?
由于JVM的多線程是通過線程輪流切換并分配處理器執?時間的?式來實現,因此在任何?個確定的時刻,?個處理器(多核處理器則指的是?個內核)都只會執??條線程中的指令。因此為了切換線程后能恢復到正確的執?位置,每條線程都需要獨?的程序計數器,各條線程之間計數器互不影響,獨?存儲。我們就把類似這類區域稱之為"線程私有"的內存。
2.3 本地方法棧(線程私有)
本地?法棧和虛擬機棧類似,只不過 Java 虛擬機棧是給 JVM 使?的,?本地?法棧是給本地?法使?的。
2.4 程序計數器(線程私有)
程序計數器的作?: ?來記錄當前線程執?的?號的。
程序計數器是?塊?較?的內存空間,可以看做是當前線程所執?的字節碼的?號指?器。
如果當前線程正在執?的是?個Java?法,這個計數器記錄的是正在執?的虛擬機字節碼指令的地址;如果正在執?的是?個Native?法,這個計數器值為空。
程序計數器內存區域是唯??個在JVM規范中沒有規定任何OOM情況的區域!
2.5 方法區(線程共享)
方法區的作?: ?來存儲被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據的。
運?時常量池是?法區的?部分,存放字?量與符號引?。
字?量 : 字符串(JDK 8 移動到堆中) 、final常量、基本數據類型的值。
符號引? : 類和結構的完全限定名、字段的名稱和描述符、?法的名稱和描述符。
3. 數據內存區域劃分
- 堆:存放new出來的對象(成員變量)
- 棧:存放方法之間的調用關系(局部變量)
- 方法區/元數據區:存放類對象(類加載之后,存放的位置)(靜態變量)
- 程序計數器:存放每個線程,下一條要執行的指令的地址
1、3是整個Java進程公用一份;2、4是每個線程都有自己的一份