JAVA虛擬機內存結構

一、JVM給JAVA應用程序帶來的影響:
1、一次編寫 到處運行
2、相對安全的內存管理和訪問機制,避免了絕大多數的內存泄露和指針越界問題
c、c++等語言需要自己去爲對象申請內存,同時主動維護其生命週期,而JAVA在JVM的自動內存管理機制下,不需要爲每個new操作去寫配對的free或者delete操作,而是交給JVM自動管理,因此不容易出現內存泄露和內存溢出等問題。但是一旦出現,排查難度就比較大了。

二、JAVA虛擬機運行時數據區的劃分

JAVA虛擬機運行時數據區分爲以下幾個部分:
方法區、虛擬機棧、本地方法棧、堆、程序計數器
其中在某些jvm實現中本地方法棧和虛擬機棧是合二爲一的

1、程序計數器

  • 一塊較小的內存空間
  • 當前線程所執行字節碼的行號指示器
  • 線程私有的內存區域:
    jvm的多線程是通過輪流切換並分配處理器時間來實現的,所以在一個確切時刻,一個處理器(對於多核處理器而言是一個內核)都會執行一條線程中的指令。因此,爲了線程切換後可以恢復到正確的執行位置,每個線程都需要有一個獨立的程序計數器
  • 唯一一個java虛擬機規範中沒有規定任何OutOfMemoryError的內存區域

    程序計數器中記錄的值:如果線程正在執行一個java方法,那麼程序計數器記錄的是正在執行的虛擬機字節碼指令的地址,如果正在執行的是一個native方法, 則計數器的值爲空。

    2、JAVA虛擬機棧

  • 線程私有的內存區域

  • 生命週期與線程相同
  • 描述java方法執行的內存模型,每個方法在執行的同時都會創建一個棧幀,用於存儲局部變量表,操作數,動態鏈接,方法出口等信息。每個方法在調用直到完成的過程,就對應一個棧幀在虛擬機棧中從入棧到出棧的過程。

    局部變量表存放了編譯器可知的各種基本數據類型(int、double…..)、對象的引用、returnAddress類型(指向一條字節碼指令的地址)。 其中64位長度的long和double數據會佔用2個局部變量空間(slot),而其他數據類型只佔用一個局部變量空間。
    局部變量表所需內存空間在編譯期間完成分配,方法運行期間並不會改變局部變量表的大小

    java虛擬機棧規定的兩種異常:

  • StackOverFlowError 如果線程請求的棧深度大於虛擬機所允許的棧的深度

  • OutOfMemoryError 在虛擬機運行動態拓展時, 如果拓展時無法申請到足夠的內存,就會拋出該異常

3、本地方法棧
與虛擬機棧類似,只是虛擬機棧爲java方法服務,本地方法棧爲native方法服務

4、堆
堆是java虛擬機管理的最大一塊內存區域,被所有線程共享。
在虛擬機啓動時創建
唯一目的是用於存放對象實例
堆可以處於物理上不連續的內存空間,只要邏輯上連續的即可

5、方法區

  • 被所有線程共享
  • 存儲已被虛擬機加載的類信息、常量、靜態變量,即時編譯器編譯後的代碼
  • 雖然java虛擬機規範把方法區描述爲堆的一個邏輯部分,但是它有一個別名non-heap,目的是爲了和堆區別開來
  • 運行時常量池是方法區的一部分

6、直接內存

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章