Java內存結構


一、介紹

  Java 的內存結構可以從兩個方面來講:內存模型和內存區域。

  內存模型:即 JMM,內存模型是抽象線程和主內存的抽象關系,即JVM在計算機內存(RAM)中的工作方式,在研究多線程時,JMM需要深入理解

  內存區域:即JVM 在程序運行時對內存的划分(強調內存划分)

二、JVM內存區域

 

 上圖時 JVM 運行時對整體架構,其中中間部分是 JVM 運行時對內存區域划分,很明顯的看到:

1、線程私有的一些區域:程序計數器、本地方法棧、虛擬機棧

2、線程公有的一些區域:方法區、堆、另外還有堆外內存(元空間等)

 

1、程序計數器

   程序計數器是線程所私有的,主要的作用就是用來標識當前線程執行到的位置(標志執行到字節碼的位置),如:在需要恢復當前線程重新執行就需要用到這個程序計數器,程序控制循環分支、跳轉、異常處理也需要用到程序計數器。

2、虛擬機棧

  每個線程在創建的時候,都會創建一個虛擬機棧,這個棧是線程私有的,線程每一次調用方法都會存入這個棧,且各個方法之間的數據傳遞也是通過這個棧進行傳遞,里面的每一個棧幀的組成大概是:局部變量表、操作數棧、動態鏈接、方法出口信息等。其生命周期與線程一致。

 

 

 

 

3、本地方法棧

  與虛擬機棧的作用十分類似,區別是虛擬機棧是為Java方法服務,即字節碼,而本地方法棧主要是為Native方法服務

  本地方法可以通過本地方法接口來訪問虛擬機內部的運行時數據區,它甚至可以直接使用本地處理器中的寄存器,直接從本地內存的堆中分配任意數量的內存

4、堆內存

  Java堆是虛擬機所管理的內存中最大的一塊區域,是所有線程所共享的一塊內存區域,Java世界里幾乎所有的對象實例都在這里分配內存,但隨着Java語言的發展,在堆里分配內存也不是那么絕對。

  Java堆是垃圾回收器管理的區域,所以也成為 “GC堆”,所以為了進行高效的垃圾回收,Java堆被邏輯上划分成三部分:

  • 新生代:即剛申請的一些內存空間
  • 老年代:即申請過了很久還在被使用的內存空間
  • 元空間(JDK8之前叫永久代):像一些方法中的操作臨時對象等,JDK1.8 之前是占用 JVM 內存,JDK1.8 之后直接使用物理內存

 

 

  堆內存的划分如上圖所示:其中 Eden、S0、S1都屬於新生代,而Old Memory 屬於老年代,Perm屬於永久代。

  默認情況下,新申請的內存都會在 Eden 內,如果在經歷一次垃圾回收后,沒有被清理的內存的年齡就會 +1 ,就會進入 S1或者S0,而隨着年齡的增長,如果年齡超過闕值,就會進入老年代,這個闕值是 GC 遍歷完整個內存后,年齡超過一半以上的內存,則會進去老年代,這個一半的年齡就是闕值。

5、方法區

  方法區同樣是所有線程共享的內存區域,它用於存儲已經被虛擬機加載的類型信息、常量、靜態變量、即時編譯器編譯后的代碼緩存等數據。

 

方法區 和 元空間 的區別:

 

 永久代和元空間都可以理解為方法區的落地實現,永久代是堆的一部分,屬於虛擬機內存(受 GC 管理),而元空間則是本機內存。

6、運行時常量池

  運行時常量是方法區的一部分,Class 文件除了有類的版本、字段、方法、接口等描述信息外,還有一項信息是常量池表,用於存放編譯期生成的各種字面量和符號引用,這部分將在類加載后存放到方法區的運行時常量池中。

  為什么需要常量池?

  一個 Java 源文件中的類、接口,編譯后產生一個字節碼文件。而 Java 中的字節碼需要數據支持,通常這種數據會很大以至於不能直接存到字節碼里,換另一種方式,可以存到常量池,這個字節碼包含了指向常量池的引用。在動態鏈接的時候用到的就是運行時常量池。
 
  • 在加載類和結構到虛擬機后,就會創建對應的運行時常量池
  • 常量池表(Constant Pool Table)是 Class 文件的一部分,用於存儲編譯期生成的各種字面量和符號引用,這部分內容將在類加載后存放到方法區的運行時常量池中
  • JVM 為每個已加載的類型(類或接口)都維護一個常量池。池中的數據項像數組項一樣,是通過索引訪問的
  • 運行時常量池中包含各種不同的常量,包括編譯器就已經明確的數值字面量,也包括到運行期解析后才能夠獲得的方法或字段引用。此時不再是常量池中的符號地址了,這里換為真實地址
    • 運行時常量池,相對於 Class 文件常量池的另一個重要特征是:動態性,Java 語言並不要求常量一定只有編譯期間才能產生,運行期間也可以將新的常量放入池中,String 類的 intern() 方法就是這樣的
  • 當創建類或接口的運行時常量池時,如果構造運行時常量池所需的內存空間超過了方法區所能提供的最大值,則 JVM 會拋出 OutOfMemoryError 異常

三、Java內存模型

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM