日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java 内存模型和 JVM 内存结构真不是一回事

發布時間:2025/4/16 java 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 内存模型和 JVM 内存结构真不是一回事 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這兩個概念估計有不少人會混淆,它們都可以說是 JVM 規范的一部分,但真不是一回事!它們描述和解決的是不同問題,簡單來說,

  • Java 內存模型,描述的是多線程允許的行為
  • JVM 內存結構,描述的是線程運行所設計的內存空間

JVM 是什么呢?它屏蔽了底層架構的差異性,是 Java 跨平臺的依據,也是每個 Java 程序員必須了解的一部分。

JVM 體系結構

Java Virtual Machine(JVM) 是一種抽象的計算機,基于堆棧架構,它有自己的指令集和內存管理。它加載 class 文件,分析、解釋并執行字節碼。基本結構如下:

如上圖所示,JVM 主要分為三個子系統:類加載器運行時數據區執行引擎

類加載器子系統

它主要功能是處理類的動態加載,還有鏈接,并且在第一次引用類時進行初始化

Loading - 加載,顧名思義,用于加載類,它有三種類加載器,根據雙親委托模型,從不同路徑進行加載:

  • Bootstrap ClassLoader - 加載 rt.jar 核心類庫,是優先級最高的加載器
  • Extension ClassLoader - 負責加載 jre\lib\ext 文件夾中的類
  • Application ClassLoader -負責加載 CLASSPATH 指定的類庫

Linking - 鏈接,動態鏈接到運行時所需的資源,分為三步:

  • Verify - 驗證:驗證生成的字節碼是否正確
  • Prepare - 準備:為所有靜態變量,分配內存并賦予默認值
  • Resolve - 解析:將 class 文件常量池中所有對內存的符號引用,替換成到方法區的直接引用

Initialization - 類初始化,類加載的最后階段,這里對靜態變量進行賦值,并執行靜態塊。(注意區分對象初始化

運行時數據區

它約定了在運行時程序代碼的數據比如變量、參數等等的存儲位置,主要包含以下幾部分:

  • PC 寄存器(程序計數器):保存正在執行的字節碼指令的地址
  • :在方法調用時,創建一個叫棧幀的數據結構,用于存儲局部變量和部分過程的結果,棧幀由以下幾部分組成:
    • 局部變量表:存儲方法調用時傳遞的參數,從0開始存儲this、方法參數、局部變量
    • 操作數棧:執行中間操作,存儲從局部變量表或對象實例字段復制的常量或變量值,以及操作結果,另外,還用來準備被調用方法的參數和接受方法調用的返回結果
    • 動態鏈接:一個指向運行時常量池的引用,將 class 文件中的符號引用(描述一個方法調用了其他方法或訪問成員變量)轉為直接引用
    • 方法返回地址:方法正常退出或拋出異常退出,返回方法被調用的位置
  • :存儲類實例對象和數組對象,垃圾回收的主要區域
  • 方法區:也被稱為元空間,還有個別名 non-heap(非堆),使用本地內存存儲 class meta-data 元數據(運行時常量池,字段和方法的數據,構造函數和方法的字節碼等),在 JDK 8 中,把 interned String 和類靜態變量移動到了 Java 堆
  • 運行時常量池:存儲類或接口中的數值字面量字符串字面量以及所有方法或字段的引用,基本上涉及到方法或字段,JVM 就會在運行時常量池中搜索其具體的內存地址
  • 本地方法棧:與 JVM 棧類似,只不過服務于 Native 方法

執行引擎

運行時數據區存儲著要執行的字節碼,執行引擎將會讀取并逐個執行。

Interpreter - 解釋器,它對字節碼的解釋很快,但執行慢,有個缺點是,當方法被多次調用時,每次都需要重新解釋。

JIT Compiler- JIT編譯器, 解決了解釋器的缺點,仍使用解釋器來轉換字節代碼,但發現有代碼重復執行時,會使用 JIT 編譯器,將整個字節碼編譯成本地代碼,將本地代碼用于重復調用,從而提高系統的性能,有以下幾部分組成:

  • 中間代碼生成器 - 生成中間代碼
  • 代碼優化器 - 負責優化上面生成的中間代碼
  • 目標代碼生成器 - 負責生成機器代碼或本地代碼
  • Profiler - 一個特殊組件,負責查找熱點,判斷該方法是否被多次調用

Garbage Collector- 垃圾收集器,收集和刪除未引用的對象。

另外,還包括執行引擎所需的本地庫(Native Method Libraries)和與其交互的 JNI 接口(Java Native Interface)。

現在來看下 Java 內存模型和 JVM 內存結構有何不同。

JVM 內存結構

常說的 JVM 內存結構指的就是上文提交到運行時數據區,其中堆、方法區被線程共享,程序計數器、棧、運行時常量池被線程獨享

它描述的是,在運行時,字節碼和代碼數據存儲的位置。

內存模型

先拋開 Java 不說,先來看下內存模型是什么?維基百科中的定義:

In computing, a memory model describes the interactions of threads through memory and their shared use of the data.

意思就是,在計算中,內存模型描述了多線程如何正確的通過內存進行交互和使用共享數據。換句話說,內存模型約束了處理器對內存的讀寫。

CPU 和內存之間通常會存在一層或多層高速緩存,這對單處理器可能沒問題,但在多處理器系統中,可能就會出現緩存一致性問題,也就是當兩個處理器(線程)同時讀取相同內存位置會發生什么?什么情況下會看到相同的值?

緩存一致性問題,在并發編程中,又被稱作可見性問題。內存模型處理器級別,為處理器彼此之間對內存寫入結果的可見性,定義了充分必要條件:

  • 強內存模型,一般說的是順序一致性,所有內存操作存在一個全序關系,每個操作都是原子的且立即對所有處理器可見
  • 弱內存模型,不限制處理器的內存操作順序,而使用特殊指令刷新或者使本地緩存失效,以便看到其他處理器的寫入,或使此處理器的寫入對其他處理器可見,這些特殊指令被稱為內存屏障

大多數處理器不會限制內存操作的順序,多線程在執行時可能會出現讓人困惑和違背直覺的結果。這是因為 CPU 為了充分利用不同類型存儲器(寄存器、高速緩存、主存)的總線帶寬,會將內存操作重新排序,以無序執行,這個動作稱為內存排序指令重排序

重排序,也被稱為編譯器優化和處理器優化,因為它既可以發生在編譯期間,也可以發生在 CPU 運行時。為了保證多線程的有序性,需要使用內存屏障禁止重排序

所以說,內存模型就是在硬件層面描述了使用內存屏障(刷新緩存或禁用指令重排序)解決多線程編程中的可見性有序性的問題。

Java 內存模型

Java 內存模型(下文簡稱 JMM)就是在底層處理器內存模型的基礎上,定義自己的多線程語義。它明確指定了一組排序規則,來保證線程間的可見性。

這一組規則被稱為 Happens-Before, JMM 規定,要想保證 B 操作能夠看到 A 操作的結果(無論它們是否在同一個線程),那么 A 和 B 之間必須滿足 Happens-Before 關系

  • 單線程規則:一個線程中的每個動作都 happens-before 該線程中后續的每個動作
  • 監視器鎖定規則:監聽器的解鎖動作 happens-before 后續對這個監聽器的鎖定動作
  • volatile 變量規則:對 volatile 字段的寫入動作 happens-before 后續對這個字段的每個讀取動作
  • 線程 start 規則:線程 start() 方法的執行 happens-before 一個啟動線程內的任意動作
  • 線程 join 規則:一個線程內的所有動作 happens-before 任意其他線程在該線程 join() 成功返回之前
  • 傳遞性:如果 A happens-before B, 且 B happens-before C, 那么 A happens-before C

怎么理解 happens-before 呢?如果按字面意思,比如第二個規則,線程(不管是不是同一個)的解鎖動作發生在鎖定之前?這明顯不對。happens-before 也是為了保證可見性,比如那個解鎖和加鎖的動作,可以這樣理解,線程1釋放鎖退出同步塊,線程2加鎖進入同步塊,那么線程2就能看見線程1對共享對象修改的結果。

Java 提供了幾種語言結構,包括 volatile, final 和 synchronized, 它們旨在幫助程序員向編譯器描述程序的并發要求,其中:

  • volatile - 保證可見性有序性
  • synchronized - 保證可見性有序性; 通過管程(Monitor)保證一組動作的原子性
  • final - 通過禁止在構造函數初始化給 final 字段賦值這兩個動作的重排序,保證可見性(如果 this 引用逃逸就不好說可見性了)

編譯器在遇到這些關鍵字時,會插入相應的內存屏障,保證語義的正確性。

有一點需要注意的是,synchronized 不保證同步塊內的代碼禁止重排序,因為它通過鎖保證同一時刻只有一個線程訪問同步塊(或臨界區),也就是說同步塊的代碼只需滿足 as-if-serial 語義 - 只要單線程的執行結果不改變,可以進行重排序。

所以說,Java 內存模型描述的是多線程對共享內存修改后彼此之間的可見性,另外,還確保正確同步的 Java 代碼可以在不同體系結構的處理器上正確運行。

小結

它們之間的關系可以這樣來個總結,實現一個 JVM 要滿足內存結構描述的組成部分,設計如何執行多個線程的時候,要滿足Java 內存模型約定的多線程語義。

轉載于:https://www.cnblogs.com/wskwbog/p/11349042.html

總結

以上是生活随笔為你收集整理的Java 内存模型和 JVM 内存结构真不是一回事的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美中文字幕一区二区三区 | 91成品视频 | 久久成人福利 | 亚洲第一成人网站 | 国产精品网站免费 | 91精品久久久久久久久久久 | 亚洲精品成人在线视频 | 91视频色| 好吊色av| 国产精品视频一区二区三 | 久久免费黄色网址 | 亚洲美免无码中文字幕在线 | 国产毛片一区二区三区va在线 | 日韩欧美一级片 | 爱爱福利社 | 精品一区二区三区无码视频 | 国产理论在线观看 | 日韩欧美国产激情 | 黄色小说在线免费观看 | 欧美性另类 | 一级片毛片 | 50一60岁老妇女毛片 | aaaaaav| 日韩Av无码精品 | 欧美激情h | 青草久久久久 | 久久精品2019中文字幕 | 男生把女生困困的视频 | 美女屁股眼视频免费 | 久草综合在线视频 | 玖色视频| 免费黄色在线 | 人人妻人人玩人人澡人人爽 | 日本女人hd | 男男在线观看 | 欧美综合自拍亚洲综合图片区 | 日韩理论片| 古装做爰无遮挡三级 | 懂色av蜜臀av粉嫩av喷吹 | 国产激情一区二区三区在线观看 | av大片免费看 | 69热在线观看 | 91成年人网站 | 成人综合激情 | 成人a在线观看 | 天堂av片 | 日本一区欧美 | 亚洲综合视频在线播放 | 激情综合区 | 久艹视频在线观看 | 国产三级日本三级在线播放 | 天堂网久久 | www.操| 亚洲男人天堂2020 | 白丝av | 另类ts人妖一区二区三区 | 色网在线看 | 亚洲色图制服丝袜 | 香蕉视频污在线观看 | 涩涩视频在线播放 | 中文字幕免费一区 | 天天撸一撸 | 亚洲精品一区二三区 | 精品免费 | 久在线播放 | 欧美男人天堂 | 一区二区三区免费在线视频 | 人妻体内射精一区二区三区 | av片子在线观看 | 日韩精品一区二区三区无码专区 | av午夜影院| 狠狠看| 久久天堂av综合合色蜜桃网 | 亚洲狼人伊人 | 亚洲制服一区 | 午夜久久久久久久久 | 亚洲乱色熟女一区二区三区 | 久久av一区二区三区漫画 | 日韩欧美国产精品综合嫩v 国产小毛片 | 精品欧美一区二区三区在线观看 | 青青草免费在线观看 | 成人免费在线电影 | 一级空姐毛片 | 好了av在线 | 涩涩视频网址 | 国产精品一区电影 | 美女xx网站| 日本中文字幕成人 | 四川丰满妇女毛片四川话 | 51ⅴ精品国产91久久久久久 | 久久久久久久久久久久 | 两女双腿交缠激烈磨豆腐 | 一级黄色录象 | 动漫美女被到爽 | 久久伊人五月天 | 亚洲一区视频 | 天堂资源站 | 日韩成人福利 | 国产精品4 |