網路上有很多關于JVM記憶體模型的文章,本文只針對JDK8的JVM記憶體模型予以小結,若有不對之處望留言指正,

其中,綠色表示執行緒私有空間,其他表示執行緒可共享空間
程式計數器 (無GC)
執行緒私有的一塊較小的記憶體空間,當前執行緒所執行的位元組碼的行號指示器,JVM的多執行緒就是通過執行緒輪流切換并分配CPU時間分片的方式來實作的,在任意指定的時刻,一個處理器(一個內核)只會執行一個執行緒中的指令,為了執行緒切換后能恢復到正確的執行位置,每個執行緒都需要有一個獨立的程式計數器,各個執行緒之間互不影響,獨立存盤,
這個區域也是唯一一個在JVM規范中沒有規定任何OutOfMemoryError情況的區域,
java虛擬機堆疊 (無GC)
生命周期與執行緒相同,是java方法執行的記憶體模型,每個方法在執行的同時會在虛擬機堆疊中創建一個堆疊幀,用于存盤區域變數表、運算元堆疊、動態鏈接、回傳值地址等資訊,每個方法從呼叫直至執行完成的程序就對應著一個堆疊幀在虛擬機堆疊中入堆疊到出堆疊的程序,出堆疊相當于清空了資料,入堆疊出堆疊的時機很明確,所以這塊區域記憶體也是不需要GC,
虛擬機堆疊有2種例外:
1、StackOverflowError: 執行緒請求的堆疊深度大于虛擬機所允許的深度,特別是在有遞回呼叫時
2、OutOfMemoryError: 虛擬機堆疊無法滿足執行緒所申請的空間需求,即使經過動態擴展任然無法滿足,將會導致該類例外的發送
本地方法堆疊 (無GC)
與虛擬機堆疊型別,主要區別在于虛擬機堆疊為虛擬機執行java方法服務,而本地方法堆疊是為運行本地native方法而服務,這塊區域也是不需要進行GC的,所謂本地方法就是一個java呼叫非java代碼的介面,該方法非java語言實作,大多數由C語言實作,Java通過JNI的方式來呼叫本地方法,而本地方法是以庫檔案的方式存放的(Unix機器上是以SO檔案形式),通過呼叫本地庫檔案的內部方法,使java可以實作和本機器的緊密聯系,呼叫系統級的各介面方法,當呼叫java方法時虛擬機會創建一個堆疊幀并壓入java堆疊,而當呼叫本地方法時,JVM會保持java堆疊不變,不會在java堆疊中壓入新的堆疊,只是簡單的動態鏈接并直接呼叫本地方法,
本地方法堆疊也有2種例外:
1、StackOverflowError: 執行緒請求的堆疊深度大于本地方法堆疊所允許的深度時
2、OutOfMemoryError: 本地方法堆疊空間需求不足,即使經過動態擴展任然無法滿足時
堆 (GC發生的區域)
堆是JVM記憶體占用最大,管理最復雜的一個區域,堆中主要存放物件的實體和陣列,也是GC主要發生的區域,
堆空間大小不滿足時將拋出OutOfMemoryError例外,
本地記憶體 (無GC)
本地記憶體,也就是通常所說的堆外記憶體,包含元資料區和直接記憶體,也稱為C-Heap,是供JVM自身行程使用的,當java堆空間不足時會觸發GC,但本身不會觸發GC
元資料區
JVM規范中的方法區用于存盤已被虛擬機加載的類資訊、常量、靜態變數、即時編譯器編譯后的代碼資料,在JDK8中,元資料區是對方法區的一個實作,但不在虛擬機中,而是使用本地記憶體,默認情況下,可用于元資料區的本地變數是沒有限制的,但可以用MaxMetaspaceSize引數來設定上限值
元資料區會拋出OutOfMemoryError例外
直接記憶體
在JDK1.4中引入的NIO模型,一種基于channel與buffer的IO方式,可以使用Native庫函式直接分配堆外記憶體,然后通過一個存盤在java堆中的DirectByteBuffer物件作為這塊記憶體的參考進行操作,能在一些場景中顯著提高性能,因為避免了而在java堆中和Native堆中來回復制資料,在作業系統IO程序中,需要把資料從用戶態copy到內核態,然后再輸出到IO設備,所以從java堆記憶體輸出到IO設備需要經過2次IO,而DirectMemory在native堆上只需要一次copy
直接記憶體同樣會拋出OutOfMemoryError例外
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/174388.html
標籤:Java
上一篇:Java中的String、StringBuffer和StringBuilder
下一篇:JAVA基礎入門到精通(階段一)

