理解JVM(一):內存結構

摘要: 原創出處 https://peijie-sh.github.io 歡迎轉載,保留摘要,謝謝!git

在JVM中,內存主要被分爲5類

JVM內存結構.jpg

Heap

  • 虛擬機內存管理中最大的一塊內存空間。
  • 存放關鍵字new建立的對象實例和數組。
  • 堆內存被全部線程共享。
  • 這塊內存區由JVM(Java虛擬機)本身管理。當使用new建立對象時,沒必要指定分配空間的大小,JVM會動態自動分配一塊區域;在程序執行過程當中,沒有指向此對象的引用時,此對象就被標記爲可被回收狀態,將由GC(垃圾回收器)在一個不肯定的時間自動回收,釋放所佔的內存空間。
  • 從內存回收的角度看,垃圾收集器大都基於分代收集算法,因此堆通常分爲新生代老年代,更細緻可劃分爲:Eden空間From Survivor空間To Survivor空間

虛擬機棧VM Stack

  • 存放8種基本類型的數據和對象引用(不是對象)。
  • 每一個線程有本身的單獨的棧。
  • 先進後出,後進先出。
  • 由於主要存放基本類型數據變量,因此分配空間比堆快。當超出變量的做用域,將由編譯器當即釋放空間。

本地方法棧Native Method Stack

  • 虛擬機棧相似,虛擬機棧爲虛擬機調用Java方法服務,本地方法棧爲虛擬機調用Native方法服務。
  • 在HotSpot虛擬機實現中,虛擬機棧本地方法棧被合併爲一個區域。

程序計數器 Program Counter Register

一塊較小的內存空間,可看做是當前線程所執行的字節碼的 行號指示器。github

經過改變計數器的值來選取下一條須要執行的字節碼指令。(分支、循環、跳轉、異常處理、線程恢復等)基礎功能都依賴與其完成。算法

特色:數組

  • 線程私有:由於 Java 虛擬機的多線程是經過 線程輪流切換 並 分配處理器執行時間 來實現的,在某一時刻,只會執行一條線程。所以,爲了線程切換後能恢復到正確的執行位置,每條線程都須要有一個獨立的程序計數器。
  • 無內存溢出:若是線程正在執行的是一個 Java 方法,這個計數器記錄的是正在 執行的虛擬機字節碼指令的地址;若是正在執行的是 Native 方法,這個計數器值則爲空(Undefined)。此內存區域是惟一一個在 Java 虛擬機程序規範中沒有規定任何 OutOfMemoryError 狀況的區域。

方法區Method Area

  • 跟堆同樣,被全部的線程共享。
  • 是一個內存邏輯區域,用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。

運行時常量池Runtime Constant Pool

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

直接內存Direct Memory

直接內存不是虛擬機運行時數據區的一部分,也不是Java虛擬機規範中定義的內存區域。 可是這部份內存也被頻繁地使用,並且也可能致使OutOfMemoryError異常出現。多線程

在JDK 1.4中新加入了NIO(New Input/Output)類,引入了一種基於通道(Channel)與緩 衝區(Buffer)的I/O方式,它可使用Native函數庫直接分配堆外內存,而後經過一個存儲 在Java堆中的DirectByteBuffer對象做爲這塊內存的引用進行操做。這樣能在一些場景中顯著 提升性能,由於避免了在Java堆和Native堆中來回複製數據。函數

相關文章
相關標籤/搜索