1、運行時資料區域
JVM虛擬機在執行Java程式時,會把它所管理的記憶體劃分為若干個不同的記憶體區域,如下圖所示,這些區域有著各自的用途,它們的生命周期也各不相同,其中,方法區和堆的生命周期與JVM虛擬機相同,隨著虛擬機行程的啟動而存在,因此,它們也是所有Java執行緒共享的資料區域;而虛擬機堆疊、本地方法堆疊和程式計數器,它們的生命周期與用戶執行緒相互依賴,隨著用戶執行緒的啟動和結束而對應地創建和銷毀,因此,它們也是執行緒私有的資料區域,也就是每個執行緒都有各自的虛擬機堆疊、本地方法堆疊和程式計數器,

各個資料區域的用途及特點分別如下:
程式計數器:指向當前執行緒正在執行的位元組碼的行號,是唯一一個不會發生OutOfMemoryError例外的區域,
虛擬機堆疊:記錄了當前執行緒所執行的方法的環境,其中的資料以堆疊幀為單位進行存盤,執行緒每當呼叫一個方法開始執行時,就會為該方法生成一個相應的堆疊幀并壓入堆疊中,每當結束一個方法的呼叫時,就將相應的堆疊幀彈出虛擬機堆疊,堆疊幀的結構如圖所示,堆疊幀里面主要有區域變數表、運算元堆疊、動態鏈接、方法回傳地址和附加資訊等,如果執行緒請求的堆疊深度超過虛擬機允許的深度,將會拋出StackOverflowError;如果虛擬機堆疊可以動態擴展,在動態擴展時如果申請不到足夠的記憶體,就會跑OutOfMemoryError,

本地方法堆疊:與虛擬機堆疊類似,只是其中對應的方法是本地方法,
方法區:記錄JVM加載的類資訊、常量、靜態變數等資料,運行時常量池是方法區的一部分,用于存盤Class檔案中常量池內的內容,比如字串常量,而且,運行時常量池還具備動態性,也就是說Java并不要求常量一定要在編譯期產生,無法滿足記憶體分配需求時,也會拋出OutOfMemoryError,(也有把方法區稱為“永久代”的說法)
堆:唯一的目的就是存放Java中的實體物件,所有的物件以及陣列都應該存盤在堆上,為了便于垃圾收集,堆又分為新生代和老年代,新生代又分為Eden區和Survivor區,為物件分配記憶體時,如果申請堆中沒有足夠的記憶體,且有無法擴展時,將會拋出OutOfMemoryError,
常說的堆就是指這里的堆,常說的堆疊就是指這里的虛擬機堆疊,更準確的說應該是虛擬機堆疊的堆疊幀中的區域變數表,
方法區和堆在邏輯上是執行緒共享的;虛擬機堆疊、本地方法堆疊和程式計數器在邏輯上是執行緒獨有的,
直接記憶體:并不是JVM運行時資料區的一部分,而指的是使用Native函式庫直接分配堆外記憶體,避免了在Java堆和Native堆中來回復制資料,在某些場景下能夠顯著提高性能(NIO場景),因此,直接記憶體不受Java堆大小的限制,但是受本機總記憶體的限制,當各個記憶體區域總和大于物理記憶體限制時,還是會導致OutOfMemoryError例外,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/295769.html
標籤:其他
