本篇包括如下內容:java
注:本篇及之後的筆記主要針對於Hotspot虛擬機。緩存
字節碼文件通過類加載子系統的處理,已經被加載進JVM中,接下來要研究的是JVM的運行時數據區。
運行時數據區:JVM在執行JAVA程序時,會把本身管理的內存分爲若干個不一樣的區域完成不一樣的功能。根據JVM規範,JVM管理內存大概分爲如下幾個部分,如圖所示:
針對於運行時數據區的劃分,在JDK8以前和以後出現了差別。
JDK8以前,JVM管理的內存大體可劃分爲堆,虛擬機棧,本地方法棧,程序計數器,方法區。在JDK8以後,方法區轉移到了本地內存中,稱爲元數據區,上圖顯示的是JDK8以後的內存劃分了,元數據區直接存在於本地內存中。安全
運行時數據區中有的部分是隨着虛擬機啓動而建立,隨着虛擬機退出而銷燬,另一些則是與線程一一對應的,隨着線程的開始與結束從而建立與銷燬。併發
線程私有:程序計數器,虛擬機棧,本地方法棧。 線程共享:堆,堆外空間(元數據區,代碼緩存等)。
JVM中主要的後臺線程主要包括如下幾個:測試
這種線程的操做是須要JVM達到安全點纔會出現。這種線程的執行類型包括"stop-the-world"的垃圾收集,線程棧收集,線程掛起以及偏向鎖撤銷。spa
這種線程是時間週期事件的體現,通常用於週期性操做的調度執行。線程
這種線程對在JVM裏不一樣種類的垃圾收集行爲提供支持。code
這種線程在運行時會將字節碼編譯成本地代碼。blog
這種線程接受信號併發送給JVM,在其內部經過調用適當的方法進行處理。生命週期
程序計數器用來存儲指向下一條指令的地址。由執行引擎根據地址來讀取下一條指令。
測試代碼以下:
public class PCRegisterTest {
public static void main(String[] args) { int i = 10; int j = 20; int k = i + j; } }
通過javap反編譯以後,主要內容以下:
其中指令地址即是存儲在程序計數器中的,執行引擎經過讀取指令地址,來找到對應的操做指令。
由於CPU分配資源採用的是時間片輪詢方式,各個線程之間是併發執行的,各個線程可能在執行到一半的時候CPU便把資源分配給了其餘線程,此時須要程序計數器記錄當前線程執行到了哪條指令(保留現場),而後從新得到CPU資源以後能夠繼續執行,因此程序計數器是須要線程私有的。