區分 JVM 內存結構、 Java 內存模型 以及 Java 對象模型 三個概念

本文由 簡悅 SimpRead 轉碼, 原文地址 https://www.toutiao.com/i6732361325244056072/面試

做者:Hollis 
來源:公衆號Hollis

Java 做爲一種面向對象的,跨平臺語言,其對象、內存等一直是比較難的知識點。並且不少概念的名稱看起來又那麼類似,不少人會傻傻分不清楚。好比本文咱們要討論的 JVM 內存結構Java 內存模型Java 對象模型,這就是三個大相徑庭的概念,可是不少人容易弄混。編程

能夠這樣說,不少高級開發甚至都搞不不清楚 JVM 內存結構、Java 內存模型和 Java 對象模型這三者的概念及其間的區別。甚至我見過有些面試官本身也搞的不是太清楚。不信的話,你去網上搜索 Java 內存模型,還會有不少文章的內容其實介紹的是 JVM 內存結構。多線程

首先,這三個概念是徹底不一樣的三個概念。本文主要對這三個概念加以區分以及簡單介紹。其中每個知識點均可以單獨寫一篇文章,本文並不會深刻介紹,感興趣的朋友能夠加入個人知識星球和球友們共同窗習。併發

JVM 內存結構學習

咱們都知道,Java 代碼是要運行在虛擬機上的,而虛擬機在執行 Java 程序的過程當中會把所管理的內存劃分爲若干個不一樣的數據區域,這些區域都有各自的用途。優化

其中有些區域隨着虛擬機進程的啓動而存在,而有些區域則依賴用戶線程的啓動和結束而創建和銷燬。在《Java 虛擬機規範(Java SE 8)》中描述了 JVM 運行時內存區域結構以下:線程

各個區域的功能不是本文重點,就不在這裏詳細介紹了。這裏簡單提幾個須要特別注意的點:翻譯

一、以上是 Java 虛擬機規範,不一樣的虛擬機實現會各有不一樣,可是通常會遵照規範。設計

二、規範中定義的方法區,只是一種概念上的區域,並說明了其應該具備什麼功能。可是並無規定這個區域到底應該處於何處。因此,對於不一樣的虛擬機實現來講,是有必定的自由度的。指針

三、不一樣版本的方法區所處位置不一樣,上圖中劃分的是邏輯區域,並非絕對意義上的物理區域。由於某些版本的 JDK 中方法區實際上是在堆中實現的。

四、運行時常量池用於存放編譯期生成的各類字面量和符號應用。可是,Java 語言並不要求常量只有在編譯期才能產生。好比在運行期,String.intern 也會把新的常量放入池中。

五、除了以上介紹的 JVM 運行時內存外,還有一塊內存區域可供使用,那就是直接內存。Java 虛擬機規範並無定義這塊內存區域,因此他並不禁 JVM 管理,是利用本地方法庫直接在堆外申請的內存區域。

六、堆和棧的數據劃分也不是絕對的,如 HotSpot 的 JIT 會針對對象分配作相應的優化。

如上,作個總結,JVM 內存結構,由 Java 虛擬機規範定義。描述的是 Java 程序執行過程當中,由 JVM 管理的不一樣數據區域。各個區域有其特定的功能。

Java 內存模型

Java 內存模型看上去和 Java 內存結構(JVM 內存結構)差很少,不少人會誤覺得二者是一回事兒,這也就致使面試過程當中常常答非所爲。

在前面的關於 JVM 的內存結構的圖中,咱們能夠看到,其中 Java 堆和方法區的區域是多個線程共享的數據區域。也就是說,多個線程可能能夠操做保存在堆或者方法區中的同一個數據。這也就是咱們常說的 「Java 的線程間經過共享內存進行通訊」。

Java 內存模型是根據英文 Java Memory Model(JMM)翻譯過來的。其實 JMM 並不像 JVM 內存結構同樣是真實存在的。他只是一個抽象的概念。JSR-133: Java Memory Model and Thread Specification 中描述了,JMM 是和多線程相關的,他描述了一組規則或規範,這個規範定義了一個線程對共享變量的寫入時對另外一個線程是可見的。

那麼,簡單總結下,Java 的多線程之間是經過共享內存進行通訊的,而因爲採用共享內存進行通訊,在通訊過程當中會存在一系列如可見性、原子性、順序性等問題,而 JMM 就是圍繞着多線程通訊以及與其相關的一系列特性而創建的模型。JMM 定義了一些語法集,這些語法集映射到 Java 語言中就是 volatile、synchronized 等關鍵字。

在 JMM 中,咱們把多個線程間通訊的共享內存稱之爲主內存,而在併發編程中多個線程都維護了一個本身的本地內存(這是個抽象概念),其中保存的數據是主內存中的數據拷貝。而 JMM 主要是控制本地內存和主內存之間的數據交互的。

在 Java 中,JMM 是一個很是重要的概念,正是因爲有了 JMM,Java 的併發編程才能避免不少問題。這裏就不對 Java 內存模型作更加詳細的介紹了,想了解更多的朋友能夠參考《Java 併發編程的藝術》。

Java 對象模型

Java 是一種面向對象的語言,而 Java 對象在 JVM 中的存儲也是有必定的結構的。而這個關於 Java 對象自身的存儲模型稱之爲 Java 對象模型。

HotSpot 虛擬機中,設計了一個 OOP-Klass Model。OOP(Ordinary Object Pointer)指的是普通對象指針,而 Klass 用來描述對象實例的具體類型。

每個 Java 類,在被 JVM 加載的時候,JVM 會給這個類建立一個 instanceKlass,保存在方法區,用來在 JVM 層表示該 Java 類。當咱們在 Java 代碼中,使用 new 建立一個對象的時候,JVM 會建立一個 instanceOopDesc 對象,這個對象中包含了對象頭以及實例數據。

這就是一個簡單的 Java 對象的 OOP-Klass 模型,即 Java 對象模型。

總結

咱們再來區分下 JVM 內存結構、 Java 內存模型 以及 Java 對象模型 三個概念。

JVM 內存結構,和 Java 虛擬機的運行時區域有關。

Java 內存模型,和 Java 的併發編程有關。

Java 對象模型,和 Java 對象在虛擬機中的表現形式有關。

關於這三部份內容,本文並未分別展開,由於涉及到的知識點實在太多,若是讀者感興趣,能夠自行學習。後面也會發文介紹這些內容,敬請期待。

最後,這三個概念很是重要,必定要嚴格區分開,千萬不要在面試中出現答非所爲的狀況。

相關文章
相關標籤/搜索