JVM詳解(三&四)運行時數據區

在這裏感謝尚硅谷JVM(宋紅康),在此記錄一下自己詳細對學習筆記,希望對你有所幫助。

視頻地址
代碼地址

chapter03&04運行時數據區

image-20200502163249675

前面學習了類加載子系統

image-20200502163650874

內存是非常重要的系統資源,是硬盤和CPU的中間倉庫及橋樑,承載着操作系統和應用程序的實時運行。JVM內存佈局規定了Java在運行過程中內存申請、分配、管理的策略,保證了JVM的高效穩定運行。不同的JVM對於內存的劃分方式和管理機制存在着部分差異。結合JVM虛擬機規範,來探討一下經典的JVM內存佈局。

image-20200502170234450

一個進程(一個虛擬機實例)對應一個紅色區域一個線程對應一個灰色區域

image-20200502212435376

一個棧幀對應一個方法

程序計數器(pc寄存器)

image-20200502212612548

若多個線程都要用

優化主要針對於堆空間方法區,虛擬機因只是出棧、入棧的結構,不需優化

95%集中在堆區,5%集中在方法區。

方法區在JDK8以後被換成了元空間,使用的是本地內存,一般情況不會出現內存溢出。

JDK8之前之後的方法區

一個JVM實例對應一個RunTime實例,對應一個運行時數據區,一個進程

image-20200503000100924

●線程是一個程序裏的運行單元。JVM允許- 一個應用有多個線程並行的執行。
●在Hotspot JVM裏, 每個線程都與操作系統的本地線程直接映射工
➢當一個Java線程準備好執行以後,此時一個操作系統的本地線程
也同時創建。Java線程執行終止後,本地線程也會回收。
●操作系統負責所有線程的安排調度到任何一一個可用的CPU上。一旦本地線程初始化成功,它就會調用Java線程中的run()方法。

●如果你使用jconsole或者是任何一個調武工具,都能看到在後臺有許多線程
在運行。這些後臺線程不包括調用public static void main (String[])的main線程以及所有這個main線程自己創建的線程。
●這些主要的後臺系統線程在Hotspot JVM裏 主要是以下幾個:
➢虛擬機線程:這種線程的操作是需要JVM達到安全點纔會出現。這些操作必須在不
同的線程中發生的原因是他們都需要JVM達到安全點,這樣堆纔不會變化。這種線
程的執行類型包括”stop- the-world"的垃圾收集,線程棧收集,線程掛起以及
偏向鎖撤銷。
➢週期任務線程:這種線程是時間週期事件的體現(比如中斷),他們一-般用於週期性
操作的調度執行。
➢GC線程:這種線程對在JVM裏不同種類的垃圾收集行爲提供了支持。
➢編譯線程:這種線程在運行時會將字節碼編譯成到本地代碼。
➢信號調度線程:這種線程接收信號併發送給JVM,在它內部通過調用適當的方法進
行處理。

程序計數器(PC寄存器)

JAVA8以後在垃圾回收方面有一些變化

JDK

JDK8

image-20200503171515736

JVM中的程序計數寄存器(Program Counter Register) 中,Register 的命名源於
CPU的寄存器,寄存器存儲指令相關的現場信息。CPU只有 把數據裝載到寄存器才能夠運行。
這裏,並非是廣義上所指的物理寄存器,或許將其翻譯爲PC計數器(或指令計數器)會更加貼切(也稱爲程序鉤子),並且也不容易引起一些不必要的誤會。JVM中的PC寄存器是對物理PC寄存器的一種抽象模擬。

image-20200503172326244

●它是一塊很小的內存空間,幾乎可以忽略不記。也是運行速度最快的存儲區域。
●在JVM規範中,每個線程都有它自己的程序計數器,是線程私有的,生命週期與線程的生命週期保持一致。
●任何時間一個線程都只有一個方法在執行,也就是所謂的當前方法。程序計數器會存儲當前線程正在執行的Java方法的JVM指令地址;或者,如果是在執行native方法,則是未指定值(undefined) 。

因爲這是一個JAVA層面的

●它是程序控制流的指示器,分支、循環、跳轉、異常處理、線程恢復等基礎
功能都需要依賴這個計數器來完成。
●字節碼解釋器工作時就是通過改變這個計數器的值來選取下–條需要執行的字節碼指令。
●它是唯一個在Java虛擬機規範中沒有規定任何OutOfMemoryError情況的區域。

image-20200503191205710

偏移地址,PC寄存器中存儲的

image-20200503191449228

image-20200503192547126

下面給出例子進行解釋

image-20200503193108928

image-20200503193137937

image-20200503193203613

image-20200503193338527

image-20200503193244856

image-20200503193404486

PC寄存器爲什麼會被設定爲線程私有?

我們都知道所謂的多線程在一個特定的時間段內只會執行其中某-一個線程的方法,CPU會不停地做任務切換,這樣必然導致經常中斷或恢復,如何保證分毫無差呢?爲了能夠準確地記錄各個線程正在執行的當前商5碼指令地址,最好的辦法自然是爲每一個線程都分配一個PC寄存器,這樣一來各個線程之間便可以進行獨立計算,從而不會出現相互干擾的情況。

image-20200503203634305

以上爲單核

由於CPU時間片輪限制,衆多線程在併發執行過程中,任何一個確定的時刻,一個處理器或者多核處理器中的一個內核,只會執行某個線程中的一條指令。

這樣必然導致經常中斷或恢復,如何保證分毫無差呢?每個線程在創建後,都會產生自己的程序計數器和棧幀,程序計數器在各個線程之間互不影響。

image-20200503204207877

串行與並行

image-20200503204649811

串行:線程排成隊依次被cpu執行。同一個時間點只有一個線程執行

並行:多個線程同時執行

併發:一個核快速地去切換線程,讓他們看着像是並行,其實是併發

垃圾回收器中【之後會講到】:

串行:用戶線程跟垃圾回收線程不能同時執行。垃圾回收線程只能有一條

並行:垃圾回收線程可以有多條,但這時候用戶的線程就在一個停止的狀態

併發:用戶線程跟垃圾線程是可以同時進行的(不一定是並行的,也肯能是交替的)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章