## 前言
Java作為一種面向對象的,跨平臺語言,其對象、內存等一直是比較難的知識點。而且很多概念的名稱看起來又那么相似,很多人會傻傻分不清楚。比如本文我們要討論的JVM內存結構、Java內存模型和Java對象模型,這就是三個截然不同的概念,但是很多人容易弄混。
可以這樣說,很多高級開發甚至都搞不不清楚JVM內存結構、Java內存模型和Java對象模型這三者的概念及其間的區別。甚至我見過有些面試官自己也搞的不是太清楚。不信的話,你去網上搜索Java內存模型,還會有很多文章的內容其實介紹的是JVM內存結構。
首先,這三個概念是完全不同的三個概念。本文主要對這三個概念加以區分以及簡單介紹。
### JVM內存結構
我們都知道,Java代碼是要運行在虛擬機上的,而虛擬機在執行Java程序的過程中會把所管理的內存劃分為若干個不同的數據區域,這些區域都有各自的用途。其中有些區域隨著虛擬機進程的啟動而存在,而有些區域則依賴用戶線程的啟動和結束而建立和銷毀。在《Java虛擬機規范(Java SE 8)》中描述了JVM運行時內存區域結構如下:

各個區域的功能不是本文重點,就不在這里詳細介紹了。這里簡單提幾個需要特別注意的點:
* 1、以上是Java虛擬機規范,不同的虛擬機實現會各有不同,但是一般會遵守規范。
* 2、規范中定義的方法區,只是一種概念上的區域,并說明了其應該具有什么功能。但是并沒有規定這個區域到底應該處于何處。所以,對于不同的虛擬機實現來說,是由一定的自由度的。
* 3、不同版本的方法區所處位置不同,上圖中劃分的是邏輯區域,并不是絕對意義上的物理區域。因為某些版本的JDK中方法區其實是在堆中實現的。
* 4、運行時常量池用于存放編譯期生成的各種字面量和符號應用。但是,Java語言并不要求常量只有在編譯期才能產生。比如在運行期,String.intern也會把新的常量放入池中。
* 5、除了以上介紹的JVM運行時內存外,還有一塊內存區域可供使用,那就是直接內存。Java虛擬機規范并沒有定義這塊內存區域,所以他并不由JVM管理,是利用本地方法庫直接在堆外申請的內存區域。
* 6、堆和棧的數據劃分也不是絕對的,如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等關鍵字**。

在Java中,JMM是一個非常重要的概念,正是由于有了JMM,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對象在虛擬機中的表現形式有關。**
- java
- 設計模式
- 設計模式總覽
- 設計原則
- 工廠方法模式
- 抽象工廠模式
- 單例模式
- 建造者模式
- 原型模式
- 適配器模式
- 裝飾者模式
- 代理模式
- 外觀模式
- 橋接模式
- 組合模式
- 享元模式
- 策略模式
- 模板方法模式
- 觀察者模式
- 迭代子模式
- 責任鏈模式
- 命令模式
- 備忘錄模式
- 狀態模式
- 訪問者模式
- 中介者模式
- 解釋器模式
- 附錄
- JVM相關
- JVM內存結構
- Java虛擬機的內存組成以及堆內存介紹
- Java堆和棧
- 附錄-數據結構的堆棧和內存分配的堆區棧區的區別
- Java內存之Java 堆
- Java內存之虛擬機和內存區域概述
- Java 內存之方法區和運行時常量池
- Java 內存之直接內存(堆外內存)
- JAVA內存模型
- Java內存模型介紹
- 內存模型如何解決緩存一致性問題
- 深入理解Java內存模型——基礎
- 深入理解Java內存模型——重排序
- 深入理解Java內存模型——順序一致性
- 深入理解Java內存模型——volatile
- 深入理解Java內存模型——鎖
- 深入理解Java內存模型——final
- 深入理解Java內存模型——總結
- 內存可見性
- JAVA對象模型
- JVM內存結構 VS Java內存模型 VS Java對象模型
- Java的對象模型
- Java的對象頭
- HotSpot虛擬機
- HotSpot虛擬機對象探秘
- 深入分析Java的編譯原理
- Java虛擬機的鎖優化技術
- 對象和數組并不是都在堆上分配內存的
- 垃圾回收
- JVM內存管理及垃圾回收
- JVM 垃圾回收器工作原理及使用實例介紹
- JVM內存回收理論與實現(對象存活的判定)
- JVM參數及調優
- CMS GC日志分析
- JVM實用參數(一)JVM類型以及編譯器模式
- JVM實用參數(二)參數分類和即時(JIT)編譯器診斷
- JVM實用參數(三)打印所有XX參數及值
- JVM實用參數(四)內存調優
- JVM實用參數(五)新生代垃圾回收
- JVM實用參數(六) 吞吐量收集器
- JVM實用參數(七)CMS收集器
- JVM實用參數(八)GC日志
- Java性能調優原則
- JVM 優化經驗總結
- 面試題整理
- 面試題1
- java日志規約
- Spring安全
- OAtuth2.0簡介
- Spring Session 簡介(一)
- Spring Session 簡介(二)
- Spring Session 簡介(三)
- Spring Security 簡介(一)
- Spring Security 簡介(二)
- Spring Security 簡介(三)
- Spring Security 簡介(四)
- Spring Security 簡介(五)
- Spring Security Oauth2 (一)
- Spring Security Oauth2 (二)
- Spring Security Oauth2 (三)
- SpringBoot
- Shiro
- Shiro和Spring Security對比
- Shiro簡介
- Session、Cookie和Cache
- Web Socket
- Spring WebFlux