JVM學習筆記(1)--java內存區域與內存溢出異常

運行時數據區域

程序計數器 Program Counter Register

可以看作是當前線程的字節碼的行號指示器,爲什麼說是當前線程呢?因爲java的多線程是通過線程輪流切換來實現的,爲了切換後能恢復到正確的執行位置,每個線程都要有一個獨立的程序計數器,之間互不影響。這塊內存區域被稱爲“線程私有”的內存。

java虛擬機棧VM Stack

  • 我們常說的棧內存就是指虛擬機棧
  • 虛擬機棧也是線程私有的
  • 生命週期與線程相同
  • 描述了java方法執行的內存模型,每個方法執行時,都會創建一個棧幀(stack frame)用於存儲局部變量表、操作數棧、動態鏈接,方法出口等信息,每個方法的調用到完成,對應着棧幀在虛擬機棧中的入棧到出棧的過程
  • 局部變量表用於存放基本數據類型(boolean,byte,char,short,int,float,long,double),對象引用,和returnAddress
  • 該區域會出現兩種異常:1.如果線程請求的棧的深度大於虛擬機棧所允許的深度,會拋出StackOverflowError異常。2.若虛擬機棧可以動態擴展(大部分虛擬機都允許),如果擴展時無法申請到足夠的內存,則會拋出OutOfMemoryError異常

本地方法棧 Native Method Stack

  • 線程私有
  • 與虛擬機棧類似,唯一區別就是虛擬機棧位虛擬機執行java方法服務,本地方法棧則虛擬機使用的native方法服務
  • 也會拋出StackOverflowError異常與OutOfMemoryError異常

java堆 java heap

  • 是一塊被所有線程共享的內存區域,在虛擬機啓動的時候創建。
  • 唯一目的就是存放對象(及數組)實例,幾乎所有對象實例都在這裏分配內存
  • 在堆中沒有內存完成實例分配,並且堆無法再拓展的時候,就會拋出OutOfMemoryError異常

方法區

  • 無法滿足內存分配時就會拋出OutOfMemoryError異常
  • 用於存儲已被虛擬機加載的類信息,常量,靜態變量,即時編譯器編譯後的代碼等

運行時常量池

  • 是方法區的一部分
  • 常量池:用於存放編譯期生成的各種字面量(1,2,“abc”稱爲字面量)和符號引用,這部分內容在類加載後進入方法區的運行時常量池存放
  • 無法滿足內存分配時就會拋出OutOfMemoryError異常

直接內存

  • 並不是虛擬機運行時數據區的一部分,是引入NIO類後出現的一塊內存。

虛擬機對象

對象內存分配

  • 指針碰撞:要求java堆是規整的!Serial,ParNew
  • 空閒列表:虛擬機維護一個列表,記錄哪些內存塊是可用的,分配的時候找到一個空間給對象,並更新列表記錄。CMS

對象的內存佈局

對象在內存中存儲的佈局可以分爲三塊:對象頭,實例數據,對齊填充
* 對象頭:對象自身的運行時數據和類型指針(對象指向他的類元數據的指針)
* 實例數據:對象存儲的有效信息
* 對齊填充:對象的大小必須是8字節的整數倍,因此不夠得需要補齊

對象的訪問定位

java程序需要通過棧中的reference來操作java堆上的具體對象
主流兩種方式來訪問:使用句柄和直接指針
直接指針節省了一次指針定位的時間

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