JVM內(nèi)存結(jié)構(gòu) VS Java內(nèi)存模型 VS Java對(duì)象模型
Java作為一種面向?qū)ο蟮?,跨平臺(tái)語(yǔ)言,其對(duì)象、內(nèi)存等一直是比較難的知識(shí)點(diǎn)。而且很多概念的名稱看起來(lái)又那么相似,很多人會(huì)傻傻分不清楚。比如本文我們要討論的JVM內(nèi)存結(jié)構(gòu)、Java內(nèi)存模型和Java對(duì)象模型,這就是三個(gè)截然不同的概念,但是很多人容易弄混。
可以這樣說(shuō),很多高級(jí)開發(fā)甚至都搞不不清楚JVM內(nèi)存結(jié)構(gòu)、Java內(nèi)存模型和Java對(duì)象模型這三者的概念及其間的區(qū)別。甚至我見(jiàn)過(guò)有些面試官自己也搞的不是太清楚。不信的話,你去網(wǎng)上搜索Java內(nèi)存模型,還會(huì)有很多文章的內(nèi)容其實(shí)介紹的是JVM內(nèi)存結(jié)構(gòu)。
首先,這三個(gè)概念是完全不同的三個(gè)概念。本文主要對(duì)這三個(gè)概念加以區(qū)分以及簡(jiǎn)單介紹。其中每一個(gè)知識(shí)點(diǎn)都可以單獨(dú)寫一篇文章,本文并不會(huì)深入介紹,感興趣的朋友可以加入我的知識(shí)星球和球友們共同學(xué)習(xí)。
JVM內(nèi)存結(jié)構(gòu)
我們都知道,Java代碼是要運(yùn)行在虛擬機(jī)上的,而虛擬機(jī)在執(zhí)行Java程序的過(guò)程中會(huì)把所管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域,這些區(qū)域都有各自的用途。
其中有些區(qū)域隨著虛擬機(jī)進(jìn)程的啟動(dòng)而存在,而有些區(qū)域則依賴用戶線程的啟動(dòng)和結(jié)束而建立和銷毀。在《Java虛擬機(jī)規(guī)范(Java SE 8)》中描述了JVM運(yùn)行時(shí)內(nèi)存區(qū)域結(jié)構(gòu)如下:
各個(gè)區(qū)域的功能不是本文重點(diǎn),就不在這里詳細(xì)介紹了。這里簡(jiǎn)單提幾個(gè)需要特別注意的點(diǎn):
1、以上是Java虛擬機(jī)規(guī)范,不同的虛擬機(jī)實(shí)現(xiàn)會(huì)各有不同,但是一般會(huì)遵守規(guī)范。
2、規(guī)范中定義的方法區(qū),只是一種概念上的區(qū)域,并說(shuō)明了其應(yīng)該具有什么功能。但是并沒(méi)有規(guī)定這個(gè)區(qū)域到底應(yīng)該處于何處。所以,對(duì)于不同的虛擬機(jī)實(shí)現(xiàn)來(lái)說(shuō),是有一定的自由度的。
3、不同版本的方法區(qū)所處位置不同,上圖中劃分的是邏輯區(qū)域,并不是絕對(duì)意義上的物理區(qū)域。因?yàn)槟承┌姹镜腏DK中方法區(qū)其實(shí)是在堆中實(shí)現(xiàn)的。
4、運(yùn)行時(shí)常量池用于存放編譯期生成的各種字面量和符號(hào)應(yīng)用。但是,Java語(yǔ)言并不要求常量只有在編譯期才能產(chǎn)生。比如在運(yùn)行期,String.intern也會(huì)把新的常量放入池中。
5、除了以上介紹的JVM運(yùn)行時(shí)內(nèi)存外,還有一塊內(nèi)存區(qū)域可供使用,那就是直接內(nèi)存。Java虛擬機(jī)規(guī)范并沒(méi)有定義這塊內(nèi)存區(qū)域,所以他并不由JVM管理,是利用本地方法庫(kù)直接在堆外申請(qǐng)的內(nèi)存區(qū)域。
6、堆和棧的數(shù)據(jù)劃分也不是絕對(duì)的,如HotSpot的JIT會(huì)針對(duì)對(duì)象分配做相應(yīng)的優(yōu)化。
如上,做個(gè)總結(jié),JVM內(nèi)存結(jié)構(gòu),由Java虛擬機(jī)規(guī)范定義。描述的是Java程序執(zhí)行過(guò)程中,由JVM管理的不同數(shù)據(jù)區(qū)域。各個(gè)區(qū)域有其特定的功能。
Java內(nèi)存模型
Java內(nèi)存模型看上去和Java內(nèi)存結(jié)構(gòu)(JVM內(nèi)存結(jié)構(gòu))差不多,很多人會(huì)誤以為兩者是一回事兒,這也就導(dǎo)致面試過(guò)程中經(jīng)常答非所為。
在前面的關(guān)于JVM的內(nèi)存結(jié)構(gòu)的圖中,我們可以看到,其中Java堆和方法區(qū)的區(qū)域是多個(gè)線程共享的數(shù)據(jù)區(qū)域。也就是說(shuō),多個(gè)線程可能可以操作保存在堆或者方法區(qū)中的同一個(gè)數(shù)據(jù)。這也就是我們常說(shuō)的“Java的線程間通過(guò)共享內(nèi)存進(jìn)行通信”。
Java內(nèi)存模型是根據(jù)英文Java Memory Model(JMM)翻譯過(guò)來(lái)的。其實(shí)JMM并不像JVM內(nèi)存結(jié)構(gòu)一樣是真實(shí)存在的。他只是一個(gè)抽象的概念。JSR-133: Java Memory Model and Thread Specification 中描述了,JMM是和多線程相關(guān)的,他描述了一組規(guī)則或規(guī)范,這個(gè)規(guī)范定義了一個(gè)線程對(duì)共享變量的寫入時(shí)對(duì)另一個(gè)線程是可見(jiàn)的。
那么,簡(jiǎn)單總結(jié)下,Java的多線程之間是通過(guò)共享內(nèi)存進(jìn)行通信的,而由于采用共享內(nèi)存進(jìn)行通信,在通信過(guò)程中會(huì)存在一系列如可見(jiàn)性、原子性、順序性等問(wèn)題,而JMM就是圍繞著多線程通信以及與其相關(guān)的一系列特性而建立的模型。JMM定義了一些語(yǔ)法集,這些語(yǔ)法集映射到Java語(yǔ)言中就是volatile、synchronized等關(guān)鍵字。
在JMM中,我們把多個(gè)線程間通信的共享內(nèi)存稱之為主內(nèi)存,而在并發(fā)編程中多個(gè)線程都維護(hù)了一個(gè)自己的本地內(nèi)存(這是個(gè)抽象概念),其中保存的數(shù)據(jù)是主內(nèi)存中的數(shù)據(jù)拷貝。而JMM主要是控制本地內(nèi)存和主內(nèi)存之間的數(shù)據(jù)交互的。
在Java中,JMM是一個(gè)非常重要的概念,正是由于有了JMM,Java的并發(fā)編程才能避免很多問(wèn)題。這里就不對(duì)Java內(nèi)存模型做更加詳細(xì)的介紹了,想了解更多的朋友可以參考《Java并發(fā)編程的藝術(shù)》。
Java對(duì)象模型
Java是一種面向?qū)ο蟮恼Z(yǔ)言,而Java對(duì)象在JVM中的存儲(chǔ)也是有一定的結(jié)構(gòu)的。而這個(gè)關(guān)于Java對(duì)象自身的存儲(chǔ)模型稱之為Java對(duì)象模型。
HotSpot虛擬機(jī)中,設(shè)計(jì)了一個(gè)OOP-Klass Model。OOP(Ordinary Object Pointer)指的是普通對(duì)象指針,而Klass用來(lái)描述對(duì)象實(shí)例的具體類型。
每一個(gè)Java類,在被JVM加載的時(shí)候,JVM會(huì)給這個(gè)類創(chuàng)建一個(gè)instanceKlass,保存在方法區(qū),用來(lái)在JVM層表示該Java類。當(dāng)我們?cè)贘ava代碼中,使用new創(chuàng)建一個(gè)對(duì)象的時(shí)候,JVM會(huì)創(chuàng)建一個(gè)instanceOopDesc對(duì)象,這個(gè)對(duì)象中包含了對(duì)象頭以及實(shí)例數(shù)據(jù)。
這就是一個(gè)簡(jiǎn)單的Java對(duì)象的OOP-Klass模型,即Java對(duì)象模型。
總結(jié)
我們?cè)賮?lái)區(qū)分下JVM內(nèi)存結(jié)構(gòu)、 Java內(nèi)存模型 以及 Java對(duì)象模型 三個(gè)概念。
JVM內(nèi)存結(jié)構(gòu),和Java虛擬機(jī)的運(yùn)行時(shí)區(qū)域有關(guān)。
Java內(nèi)存模型,和Java的并發(fā)編程有關(guān)。
Java對(duì)象模型,和Java對(duì)象在虛擬機(jī)中的表現(xiàn)形式有關(guān)。
關(guān)于這三部分內(nèi)容,本文并未分別展開,因?yàn)樯婕暗降闹R(shí)點(diǎn)實(shí)在太多,如果讀者感興趣,可以自行學(xué)習(xí)。后面也會(huì)發(fā)文介紹這些內(nèi)容,敬請(qǐng)期待。
***,這三個(gè)概念非常重要,一定要嚴(yán)格區(qū)分開,千萬(wàn)不要在面試中出現(xiàn)答非所為的情況。
【本文是51CTO專欄作者Hollis的原創(chuàng)文章,作者微信公眾號(hào)Hollis(ID:hollischuang)】