Java內(nèi)存模型即Java Memory Model,簡稱JMM。JMM定義了Java 虛擬機(jī)(JVM)在計算機(jī)內(nèi)存(RAM)中的工作方式。
Java的內(nèi)存模型,采用的是共享內(nèi)存模型,線程之間的共享變量存儲在主內(nèi)存(main memory)中,每個線程都有一個私有的本地內(nèi)存(local memory),本地內(nèi)存中存儲了該線程以讀/寫共享變量的副本。
Java內(nèi)存區(qū)域的劃分
Java內(nèi)存區(qū)域主要是指運(yùn)行時數(shù)據(jù)區(qū),包括程序計數(shù)器、虛擬機(jī)棧、堆、方法區(qū)、運(yùn)行時常量池和本地方法棧
[圖片上傳失敗...(image-c1e913-1530195539373)]
程序計數(shù)器
程序計數(shù)器又被稱之為PC寄存器。
每個虛擬機(jī)線程都有自己的程序計數(shù)器,用于保存虛擬機(jī)正在執(zhí)行字節(jié)碼指令的地址。
虛擬機(jī)棧
每個Java虛擬機(jī)線程都有自己的私有的Java虛擬機(jī)棧,和線程同時創(chuàng)建,用于存儲棧幀。
堆
堆是可供各個線程共享的運(yùn)行時的內(nèi)存區(qū)域,也是供所有類實(shí)例和數(shù)組對象分配內(nèi)存的區(qū)域。
Java堆是在虛擬機(jī)啟動的時候就被創(chuàng)建,它存儲了被垃圾收集器所管理的各種對象。
方法區(qū)
方法區(qū)是可供各個線程共享的運(yùn)行時的內(nèi)存區(qū)域。是用于存儲每一個類的結(jié)構(gòu)信息。
運(yùn)行時常量池
運(yùn)行時常量池是每一個類或接口的常量池的運(yùn)行時表現(xiàn)形式,包含了若干種不同的常量:從編譯器可知的數(shù)值字面量到必須運(yùn)行期解析后才能獲得的方法或字段引用。
每一個運(yùn)行時常量池都分配在Java虛擬機(jī)的方法之中,在類和接口被加載到虛擬機(jī)之后,對應(yīng)的常量池就被創(chuàng)建出來了。
本地方法棧
本地方法棧是用于Java虛擬機(jī)存儲native方法。如果Java虛擬機(jī)不支持native方法,可以是沒有這個本地方法棧的,如果支持本地方法棧,那么這個棧一般會在線程創(chuàng)建的時候按照線程分配。
Java的內(nèi)存模型JMM
Java虛擬機(jī)規(guī)范中定義了Java內(nèi)存模型的規(guī)范,原始的Java內(nèi)存模型存在一些不足,因此Java內(nèi)存模型在Java1.5時被重新修訂。這個版本的Java內(nèi)存模型在到現(xiàn)在仍然在使用。
JMM規(guī)定了一個線程如何和何時可以看到由其他線程修改過后的共享變量的值,以及在必須時如何同步的訪問共享變量。
[圖片上傳失敗...(image-4234bd-1530195517645)]
可以在線程之間共享的內(nèi)存被稱之為堆內(nèi)存或共享內(nèi)存。所有實(shí)例字段,static字段和數(shù)組元素都存儲在堆內(nèi)存中,局部變量,形式方法參數(shù)和異常處理參數(shù)絕不會再線程間共享,并且不受內(nèi)存模型的影響。
如果線程A與線程B之間要通信的話,必須要經(jīng)歷下面2個步驟:
1)線程A把本地內(nèi)存A中更新過的共享變量刷新到主內(nèi)存中去。
2)線程B到主內(nèi)存中去讀取線程A之前已更新過的共享變量。