Java內(nèi)存模型(Java Memory Mode,JMM)
Java的內(nèi)存模型指定了Java虛擬機(jī)如何與計(jì)算機(jī)的主存(RAM)進(jìn)行工作谱煤,如上圖所示摊求,理解Java內(nèi)存模型對(duì)于編寫(xiě)行為正確的并發(fā)程序是非常重要的。在JDK1.5以前的版本中刘离,Java內(nèi)存模型存在著一定的缺陷室叉,在JDK1.5的時(shí)候睹栖,JDK官方對(duì)Java內(nèi)存模型重新進(jìn)行了修訂,在JDK1.8及最新的JDK版本都沿用了JDK1.5修訂的內(nèi)存模型茧痕。
Java的內(nèi)存模型決定了一個(gè)線(xiàn)程對(duì)共享變量的寫(xiě)入何時(shí)對(duì)其他線(xiàn)程可見(jiàn)磨淌,Java內(nèi)存模型定義了線(xiàn)程和主內(nèi)存之間的抽象關(guān)系,具體如下:
- 共享變量存儲(chǔ)于主內(nèi)存之中凿渊,每個(gè)線(xiàn)程都可以訪問(wèn)。
- 每個(gè)線(xiàn)程都有私有的工作內(nèi)存或者稱(chēng)為本地內(nèi)存缚柳。
- 工作內(nèi)存只存儲(chǔ)該線(xiàn)程對(duì)共享變量的副本埃脏。
- 線(xiàn)程不能直接操作主內(nèi)存,只有先操作本地內(nèi)存之后才能寫(xiě)入主內(nèi)存秋忙。
-
工作內(nèi)存和Java內(nèi)存模型一樣也是一個(gè)抽象的概念彩掐,它其實(shí)并不存在,它涵蓋了緩存灰追、寄存器堵幽、編譯器優(yōu)化以及硬件等。
JVM內(nèi)存模型
1弹澎、Class Loader(類(lèi)加載器)就是將Class文件加載到內(nèi)存朴下,再說(shuō)的詳細(xì)一點(diǎn)就是,把描述類(lèi)的數(shù)據(jù)從Class文件加載到內(nèi)存苦蒿,并對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)殴胧、轉(zhuǎn)換解析和初始化,最終形成可以被虛擬機(jī)直接使用的Java類(lèi)型佩迟,這就是類(lèi)加載器的作用团滥。
2、Run Data Area(運(yùn)行時(shí)數(shù)據(jù)區(qū)) 就是我們常說(shuō)的JVM管理的內(nèi)存了报强,也是我們這里主要討論的部分灸姊。運(yùn)行數(shù)據(jù)區(qū)是整個(gè)JVM的重點(diǎn)。我們所有寫(xiě)的程序都被加載到這里秉溉,之后才開(kāi)始運(yùn)行力惯。這部分也是我們這里將要討論的重點(diǎn)。
數(shù)據(jù) | 描述 |
---|---|
Program Counter Register(程序計(jì)數(shù)器) | 線(xiàn)程私有召嘶、指向下一條要很執(zhí)行的指令 |
Java Stack(Java虛擬機(jī)棧) | 線(xiàn)程私有夯膀,生命周期與線(xiàn)程相同。描述的是Java方法執(zhí)行的內(nèi)存模型:每個(gè)方法被執(zhí)行的時(shí)候都會(huì)同時(shí)創(chuàng)建一個(gè)棧幀(Stack Frame)用于存儲(chǔ)局部變量表苍蔬、操作棧诱建、動(dòng)態(tài)鏈接、方法出口 |
Native Method Stack(本地方法棧) | 為虛擬機(jī)使用到的Native 方法服務(wù) |
Heap(線(xiàn)程共享) | 所有的對(duì)象實(shí)例以及數(shù)組都要在堆上分配碟绑,是垃圾收集器管理的主要區(qū)域俺猿。由于現(xiàn)在收集器基本采用的分代收集算法茎匠,所以Java堆中還可以細(xì)分:新生代和老生代,更細(xì)致一點(diǎn)的有Eden空間押袍、From Survivor空間诵冒、To Survivor空間等。 |
Method Area(方法區(qū)) | 被多個(gè)線(xiàn)程共享的內(nèi)存區(qū)域谊惭,它主要用于存儲(chǔ)已經(jīng)被虛擬機(jī)加載的類(lèi)信息汽馋、常量、靜態(tài)變量圈盔、JIT編譯后的代碼等數(shù)據(jù)豹芯。 |
3、Execution engine(執(zhí)行引擎) 是Java虛擬機(jī)最核心的組成部分之一驱敲。執(zhí)行引擎用于執(zhí)行指令铁蹈,不同的java虛擬機(jī)內(nèi)部實(shí)現(xiàn)中,執(zhí)行引擎在執(zhí)行Java代碼的時(shí)候可能有解釋執(zhí)行(解釋器執(zhí)行)和編譯執(zhí)行(通過(guò)即時(shí)編譯器產(chǎn)生本地代碼執(zhí)行众眨,例如BEA JRockit)握牧,也有可能兩者兼?zhèn)洹H魏蜫VM specification實(shí)現(xiàn)(JDK)的核心都是Execution engine娩梨,不同的JDK例如Sun 的JDK 和IBM的JDK好壞主要就取決于他們各自實(shí)現(xiàn)的Execution engine的好壞沿腰。
4、Native interface 與native libraries交互狈定,是其它編程語(yǔ)言交互的接口矫俺。當(dāng)調(diào)用native方法的時(shí)候,就進(jìn)入了一個(gè)全新的并且不再受虛擬機(jī)限制的世界掸冤,所以也很容易出現(xiàn)JVM無(wú)法控制的native heap OutOfMemory厘托。
JVM和JMM之間的關(guān)系
JMM中的主內(nèi)存、工作內(nèi)存與JVM中的Java堆稿湿、棧铅匹、方法區(qū)等并不是同一個(gè)層次的內(nèi)存劃分,這兩者基本上是沒(méi)有關(guān)系的饺藤,如果兩者一定要勉強(qiáng)對(duì)應(yīng)起來(lái)包斑,那從變量、主內(nèi)存涕俗、工作內(nèi)存的定義來(lái)看罗丰,主內(nèi)存主要對(duì)應(yīng)于Java堆中的對(duì)象實(shí)例數(shù)據(jù)部分,而工作內(nèi)存則對(duì)應(yīng)于虛擬機(jī)棧中的部分區(qū)域再姑。從更低層次上說(shuō)萌抵,主內(nèi)存就直接對(duì)應(yīng)于物理硬件的內(nèi)存,而為了獲取更好的運(yùn)行速度,虛擬機(jī)(甚至是硬件系統(tǒng)本身的優(yōu)化措施)可能會(huì)讓工作內(nèi)存優(yōu)先存儲(chǔ)于寄存器和高速緩存中绍填,因?yàn)槌绦蜻\(yùn)行時(shí)主要訪問(wèn)讀寫(xiě)的是工作內(nèi)存霎桅。