JVM基礎:JVM內存模型簡單介紹

下面是我在網上找的JVM內存圖,非常直觀,貼在下面,供大家學習……
在這裏插入圖片描述
下面分別介紹一下圖中各個小方塊的作用和存的東西,能力有限,如果有錯誤,希望大家指正

PC寄存器

一塊很小的內存空間,用於記錄下一條CPU要運行的指令,各個線程之間是獨立擁有自己私人的PC寄存器

  • 當執行Java代碼時:存放的Java字節碼地址
  • 當執行native方法時:則程序計數器爲空

JAVA虛擬機棧

這也是是線程私有內存空間,和線程一起創建,它保存方法的局部變量部分結果,並參與方法的調用和返回

  • 棧的大小可以設置爲動態擴展或者固定大小
  • 可以使用 -Xss參數來設置棧的固定大小
  • 如果超過固定大小,程序則會拋出StackOverflowError異常
  • 如果設定爲動態擴展,超過內存範圍後,拋出OutOfMemoryError異常

棧幀

每個線程擁有獨立的棧,而每個棧中的元素就稱爲棧幀,棧幀保存上下文數據。在棧幀中,存放的信息有方法的局部變量表、操作數棧、動態鏈接方法和返回地址等信息

出入棧對應的操作
  • 入棧:表示方法的調用
  • 出棧:表示方法的返回
局部變量表
  • 存放方法的參數局部變量
  • 如果需要在方法內進行回收一個局部變量,可以將這個變量其設置爲null或者在它超出範圍後 ,對其進行 “複用”
  • 方法外的局部變量會自動回收

本地方法棧

本地方法棧和Java虛擬機棧的功能很相似,JAVA虛擬機用於管理JAVA函數的調用,而本地方法棧用於管理本地方法的調用,本地方法棧不是用Java實現的,而是用C實現的

Java堆

JAVA運行時內存中最重要的部分,幾乎所有的對象和數組都是在堆中分配空間的。java的堆分爲新生代老年代兩部分,從開頭的圖中可以看出,他是被線程共享的

新生代

存放剛剛產生對象和年輕的對象,新生代有可以分爲以下3個空間

  • eden : 伊甸園,即對象的出生地,大部分對象剛剛建立時,通常會存放在這裏
  • survivor space0survivor space1 : 倖存者空間,又稱爲from spaceto space,存放其中的對象是經歷過一次垃圾回收了的,並倖存下來的對象或者數組

老年代 (the space)

如果對象一直沒有被回收,生存的足夠長,到了指定年齡的對象就會被移入老年代。

方法區 :

類加載器,將硬盤中的class文件加載到內存的class content中,然後安裝JVM規範對class content進行解析,解析完後的對象(Class 對象),就放在方法區

  • 方法區是一種規範,元空間是JDK8虛擬機中對方法區的一個具體的實現
  • 可以通過MetaspaceSize、MaxMetaspaceSize調節大小(JDK8以前稱爲永久區
  • 將MetaspaceSize和MaxMetaspaceSize設置成一樣大,可以防止內存抖動,建議設置爲物理內存的132\frac{1}{32}
  • JDK1.8以後,方法區的具體實現有永久區改爲了元空間,而元空間數據是放在本地內存中,而非JVM內存,這樣有利於存放更多更大的元數據

元數據

主要是class類中的各種信息,可以將他們分類如下:

類型信息

包括類的完整名稱、父類的完整名稱、類型修飾符(public/protected/private)、類型的直接接口類表

常量池

包括這個類方法、域等信息所引用的常亮信息,只要常亮池中的類沒有被任何地方引用,就可以被回收。

域信息

包括域名稱、域類型、域修飾符

方法信息

包括方法名稱、返回類型、方法參數、方法修飾符、方法字節碼、操作數棧、方法幀棧的局部變量區大小、異常表。

回收的條件

  • 所有該類的實例被回收
  • 且裝載該類的ClassLoader被回收

總結

上面的知識可能有些零散和晦澀,瞭解JVM的存放,可以讓我們理解代碼運行的邏輯,上面知識如有問題或者我有其他的新發現,我會及時更新

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