一張圖看懂JVM(本文以1.7版本爲例,1.8永久代更改爲元空間自行總結)
注意,這裏所講的主內存、工作內存與Java內存區域中的Java堆、棧內存、方法區等並不是同一個層次的內存劃分。如果勉強類比,從變量、主內存、工作內存的定義來看,主內存主要對應於Java堆中對象實例數據部分,而工作內存則對應於虛擬機棧中使用的部分內存區域;從更低層次類比,主內存就直接對應於物理硬件的內存,而爲了獲取更好的運行速度,虛擬機(甚至是硬件系統本身的優化措施)可能會讓內存優先存儲於寄存器和高速緩存中,因爲程序運行時主要訪問讀寫的是工作內存。
而主內存與工作內存之間具體的交互協議,即一個變量如何從主內存拷貝到工作內存、如何從工作內存同步回主內存之間的實現細節,Java內存模型中定義了8種操作來完成。
而且還規定在執行上述8種基本操作時必須滿足如下規則:
不允許read和load、store和write操作之一單獨出現,即不允許一個變量從主內存讀取了但工作內存不接受,或者從工作內存發起了回寫了但主內存不接受的情況出現。
不允許一個線程丟棄它的最近的assign操作,即變量在工作內存中改變了之後必須把該變化同步回主內存。
不允許一個線程無原因地(沒有發生任何assign操作)把數據從線程的工作內存同步回主內存中。
一個新的變量只能在主內存中“誕生”,不允許在工作內存中直接使用一個未被初始化(load或assign)的變量,換句話說,就是對一個變量實施use、store操作之前,必須先執行過了assign和load操作。
一個變量在同一時刻只允許一條線程對其進行lock操作,但lock操作可以被同一條線程重複執行多次,多次執行lock後,只有執行相同次數的unlock操作,變量纔會被解鎖。
如果對一個變量執行lock操作,那將會清空工作內存中此變量的值,在執行引擎使用這個變量前,需要重新執行load或assign操作初始化變量的值。
如果一個變量事先沒有被lock操作鎖定,那就不允許對它執行unlock操作,也不允許去unlock一個被其他線程鎖定住的變量。
對一個變量執行unlock操作之前,必須先把此變量同步回主內存中(執行store、write操作)。
以上8種內存訪問操作以及上述規則限定,再加上volatile的一些特殊規定以及final不可變特性,就已經完成確定了JAVA程序中那些內存訪問操作在併發下是安全的!
JVM參數總結
爲了方便大家對於JVM有關參數有一個參照,如下:
後記
讀到這裏,小編希望能夠對大家溫習基礎知識起到一定的幫助,特別是從事Java開發工作時間並不長的朋友希望本文能對你們有所促進,因爲根據作者的經驗,有時候很多從事Java開發工作好幾年的同學,都會對這些知識點產生模糊的認識,一方面是目前各類Java開源工具比較完備,另一方面是很多人從事的是業務研發工作,時間久了難免會對基礎知識有所遺忘。在上面的部分中還有一塊垃圾回收的知識點沒有總結到,基於篇幅的原因後面再單獨給大家總結!謝謝你們的關注~