Java內存區域

根據Java虛擬機規範,Java虛擬機會把Java的所管理的內存分成幾個區域,分別爲:程序計數器,Java虛擬機棧,本地方法棧,堆,方法區

通過一張圖來了解一下:
在這裏插入圖片描述
先要說明的一點是,java虛擬機棧,本地方法棧和程序計數器是線程私有的,方法區,堆是線程共享的,接下來逐一介紹

程序計數器

  • 程序計數器是一塊較小的內存空間
  • 可以把程序計數器理解爲方法執行的行號指標,字節碼解釋器可以通過改變這個計數器的值來選取下一條需要執行的字節碼指令。實現分支,循環,跳轉,異常處理,線程恢復等基礎功能都需要依賴這個計數器來完成。
  • 程序計數器是線程私有的,爲什麼是線程私有的?即使Java中的多線程,高併發,他們只是在宏觀上實現併發,但不是並行。所以多個線程時通過切換來分配cpu的時間片,任何一個時刻,一個處理器都只會執行一條線程中的指令,需要程序計數器來保證切換後線程能恢復到正確的執行位置,這樣就能理解程序計數器爲什麼是線程私有的。
  • 如果線程執行的是普通方法,那麼程序計數器記錄的是正在執行的虛擬機字節碼指令的地址;如果線程執行的是native方法,那麼程序計數器爲空。
  • 該區域沒有規定任何OutOfMemoryError

虛擬機棧

  • 虛擬機棧也是線程私有的
  • 虛擬機棧描述的是Java方法的內存模型,每個方法在執行的同時都會創建一個棧幀,在棧幀中有局部變量表,操作數棧,動態鏈接,方法接口等信息。每一個方法執行的過程就是棧幀入棧出棧的過程
  • 局部變量表存放了編譯期間可知的基本數據類型,對象引用,局部變量表所需的內存空間在編譯期間完成確定,在方法的執行過程中,不會改變局部變量表的大小。
  • 規定了兩種異常,棧深度超過允許-StackOverflowError,無法申請足夠內存-OutOfMemoryError

本地方法棧

  • 本地方法棧與虛擬機棧發揮的作用相同,只不過本地方法棧是針對Native方法,而Java虛擬機棧是針對Java方法。

  • 堆是共享的一塊內存區域
  • 堆內存很大,是垃圾回收的主要陣地
  • 幾乎所有的對象都在堆上分配內存
  • Java堆可以分爲新生代,老年代,而HotSpot實現的jvm中還有永久代。新生代還可以分爲Eden,From Survivor,To Survivor
  • 堆溢出時,會拋OutOfMemoryError
  • -xmx和-xms控制堆的最小和最大分配空間

方法區

  • 方法區是共享的區域
  • 方法區存儲已經被虛擬機加載的類信息,常量,靜態變量,編譯後的代碼等數據

方法區是否在堆中?方法區和永久代是什麼關係?

  首先需要明白的是方法區是Java虛擬機規範所規定的一塊區域,至於怎麼去實現那是虛擬機的事情,而Hotspot在jdk7之前,將方法區放到了堆中,並將gc分代算法擴展到方法區,所以將方法區稱爲永久代,這僅僅是對Hotspot而言,其他虛擬機則不存在。而在後續過程中,由於這種實現有很多的問題,所以jdk7中,Hotspot將字符串常量池移除永久代,並計劃使用本地內存來實現永久代。在jdk8中,提出了元空間的概念,元空間使用的本地內存,存儲類的元信息,而常量池靜態變量仍然留在堆中,這時永久代就已經不存在了。

發佈了117 篇原創文章 · 獲贊 283 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章