天天看點

深入了解 Java 虛拟機 學習:Java虛拟機記憶體區域

Java 虛拟機 其他相關部落格

深入了解 Java 虛拟機 學習:總結 GC 的知識點,面試問 GC 有這一篇就足夠了

深入了解 Java 虛拟機 學習:對象通路

一.運作時資料區域

Java 虛拟機在執行 Java 程式的過程中會把它所管理的記憶體劃分為若幹個不同的資料區域。這些區域都有各自的用途,以及建立和銷毀時間,有的區域随着虛拟機程序的啟動而存在,有些區域則是依賴使用者線程的啟動和結束而建立和銷毀。根據《 Java 虛拟機規範(第二版)》的規定,Java 虛拟機所管理的記憶體将會包含以下幾個運作時資料區域

1.運作時資料區域圖
深入了解 Java 虛拟機 學習:Java虛拟機記憶體區域
2.程式設計器:
  • 較小的記憶體空間
  • 作用:目前線程執行的位元組碼的型号訓示器
  • 工作:通過改變這個計數器的值來選取下一條需要執行的位元組碼指令,分支,循環,跳轉,異常處理,線程恢複等基礎功能
  • 線程私有:每條線程都有一個獨立的程式設計器,各條線程之間的計數器互不影響,獨立存儲
3.Java 虛拟機棧
  • 線程私有:生命周期與線程相同
  • 描述:Java 方法執行的記憶體模型,每個方法被執行的時候都會同時建立一個棧幀,用于存儲局部變量表,操作棧,動态連結,方法出口等資訊。每一個方法被調用直至執行完成的過程,就對應着一個棧幀在虛拟機棧種從入棧到出棧的過程
  • 棧:大多數說的棧就是虛拟機棧,或者說是虛拟機棧種的局部變量表部分
  • 局部變量表:基本資料類型,對象引用和 returnAddress 類型
  • 其中64位長度的 long 和 double 類型的資料會占用2個局部變量空間,其餘的資料類型隻占用1個。局部變量表所需要的記憶體空間在編譯期間完成配置設定,當進入一個方法時,這個方法需要在幀中配置設定多大的局部變量空間是完全确定的,在方法運作期間不會改變局部變量表的大小
4.本地方法棧
  • 1.作用:與虛拟機棧所發揮的作用是非常相似的
  • 2.和虛拟機棧的差別: 虛拟機棧為虛拟機執行 Java 方法(也就是位元組碼)服務,而本地方法棧則是為虛拟機使用到的 Native 方法服務,有的虛拟機會直接把本地方法棧和虛拟機棧合二為一。
5.Java堆
  • Java虛拟機中管理中,記憶體最大的一塊
  • 線程共享:Java 堆是被是以線程共享的一塊記憶體區域,在虛拟啟動時建立
  • 作用:用來存放對象執行個體,幾乎是以的對象執行個體都在這裡配置設定
  • GC堆:Java堆是體積收集器管理的主要區域,是以很多時候也被稱之為“GC堆”
  • 記憶體回收角度:由于現在收集器基本都是采用分代收集算法,是以 Java 堆中還可以細分成:新生代和老年代,再細緻一點的有 Eden 空間,From Survivor 空間,To Survivor 空間等
  • 記憶體配置設定角度:線程共享的Java堆中可能劃分出多個線程私有的配置設定緩沖區,不過怎麼劃分,都與存放内容無關,無論那個區域存儲的都依然是對象執行個體,進一步劃分是更好地回收記憶體,或者更快的配置設定記憶體
6.方法區
  • 永久代:很多人願意把方法區稱為 “永久代”,本質上來講兩者并不等價,僅僅時因為 HotSpot 虛拟機的設計團隊選擇把 GC 分代收集擴充至方法區,或者說使用永久代來實作 方法區而已,對于其他虛拟機(如 BEA JRockit ,IBM J9等)來說時不存在永久代的概念的
  • 線程共享:與Java堆一樣,是各個線程共享的記憶體區域
  • 作用:用于存儲已被虛拟機加載的類資訊,常量,靜态變量,即時編譯器編譯後的代碼等資料
  • Java 虛拟機規範對這個區域的限制還是比較寬松的,除了和 Java 堆一樣不需要連續的記憶體和可以選擇固定大小或者可以擴充外,還可以選擇不實作垃圾收集。垃圾收集在這個區域還是比較少出現的,但并非資料進入方法區就如永久代的名字一樣 “永久”存在了,這個區域的記憶體回收目标主要是針對常量池的回收和對類型的解除安裝