1. 程式人生 > >淺談JVM記憶體分配

淺談JVM記憶體分配

JVM 記憶體分配

  由於Java程式是交由JVM執行的,所以我們在談Java記憶體區域劃分的時候事實上是指JVM記憶體區域劃分。如下是具體java程式的執行過程:
在這裡插入圖片描述
 首先Java原始碼檔案(.java字尾)會被Java編譯器編譯為位元組碼檔案(.class字尾),然後由JVM中的類載入器載入各個類的位元組碼檔案,載入完畢之後,交由JVM執行引擎執行。在整個程式執行過程中,JVM會用一段空間來儲存程式執行期間需要用到的資料和相關資訊,這段空間一般被稱作為Runtime Data Area(執行時資料區),也就是我們常說的JVM記憶體。因此,在Java中我們常常說到的記憶體管理就是針對這段空間進行管理(如何分配和回收記憶體空間)。

執行時資料區通常包括這幾個部分:

1.程式計數器(Program Counter Register)、
2.虛擬機器棧(VM Stack)、
3.本地方法棧(Native Method Stack)、
4.方法區(Method Area)、
5.堆(Heap)。 如下圖所示:
在這裡插入圖片描述

執行時儲存區具體儲存了哪些資料?

1. 程式計數器:
* 本質:程式計數器本質上是一塊較小的記憶體空間。
可以把程式計數器簡單地看作是當前執行緒所執行的位元組碼的行號指示器。 位元組碼直譯器在工作時,通過改變程式計數器的值來選取下一條需要執行的位元組碼指令。 除此之外,程式的分支、迴圈、跳轉、異常處理、執行緒恢復等基本功能都需要依賴程式計數器來完成。


* 特性:程式計數器是一個個執行緒私有記憶體。每個執行緒都私有一個程式計數器,用來記錄執行緒當前執行的位置,好讓執行緒恢復執行的時候知道上一次執行的位置。所以各個執行緒之間的計數器相互獨立,互補影響。
 若執行緒正在執行的是一個Java方法,那麼當前執行緒的程式計數器記錄的是正在執行的虛擬機器位元組碼指令的地址;若執行緒正在執行的是一個Native方法,則這個計數器值為空。 注:Native方法是指不使用Java語言寫的方法,或者是使用Java語言寫的直接操控計算機硬體的方法。
2. java 棧:
* 本質:JVM棧是用來描述Java方法執行過程的一個記憶體模型。
  JVM棧中存放著一個個棧幀,每個棧幀都對應著一個Java方法。 當一個Java方法被執行時,JVM會在JVM棧中建立一個棧幀
,用於儲存:區域性變量表、運算元棧、動態連結、方法出口等資訊。
每一個Java方法被呼叫到執行完成的過程,都對應著一個個棧幀在JVM棧中的入棧和出棧。
* 特性:JVM棧是執行緒私有的,每一個執行緒擁有一個獨立的JVM棧,這個執行緒中所要執行的方法就會在它所對應的JVM棧中建立棧幀。
3. 堆:
* 本質:堆記憶體的唯一目的就是存放所有的物件例項。
 Java中的堆是用來儲存物件本身的以及陣列(當然,陣列引用是存放在Java棧中的)。Java的垃圾回收機制會自動進行處理,這部分空間也是Java垃圾收集器管理的主要區域,又稱GC堆。
 從jdk1.7 之後,常量池就存放在堆中,而不是在方法區。類中不被關鍵字static修飾,產生一個物件,則存放在堆中。
在堆中有一個非常重要的部分就是執行時常量池,它是每一個類或介面的常量池的執行時表示形式,在類和介面被載入到JVM後,對應的執行時常量池就被創建出來。當然並非Class檔案常量池中的內容才能進入執行時常量池,在執行期間也可將新的常量放入執行時常量池中,比如String的intern方法。
* 特性:堆是被所有執行緒共享的,在JVM中只有一個堆。
4. 方法區:
* 本質:方法區也是JVM需要使用的一塊記憶體區域,它用來儲存已經被JVM載入的類的資訊、常量、靜態變數(static修飾)、編譯後的程式碼等資料。 也是被執行緒共享的區域。
注:在JVM規範中,沒有強制要求方法區必須實現垃圾回收。很多人習慣將方法區稱為“永久代”,是因為HotSpot虛擬機器以永久代來實現方法區,從而JVM的垃圾收集器可以像管理堆區一樣管理這部分割槽域,從而不需要專門為這部分設計垃圾回收機制。不過自從JDK7之後,Hotspot虛擬機器便將執行時常量池從永久代移除了。
5. 本地方法棧:
* 本質: 本地方法棧則是為執行本地方法(Native Method)服務的,用於管理本地方法的呼叫,本地方法不是java實現的,而是使用C實現的。在JVM規範中,並沒有對本地方發展的具體實現方法以及資料結構作強制規定,虛擬機器可以自由實現它。在HotSopt虛擬機器中直接就把本地方法棧和Java棧合二為一,不區分本地方法棧和虛擬機器棧。
(HotSpot VM,它是Sun JDK和OpenJDK中所帶的虛擬機器,也是目前使用範圍最廣的Java虛擬機器。)

談談棧與堆的儲存:

* 棧是執行單位,堆是儲存單位 。
1.堆(物件):
 引用型別的變數,其記憶體分配在堆上或者常量池(字串常量,基本資料型別常量),需要通過new等方式建立。
 堆記憶體的主要作用是存放執行時new建立的物件。(主要用於存放物件,存取速度慢,可以執行時動態分配記憶體,生存期不需要提前確定)。
2.棧(基本資料型別變數,物件的引用變數):
 基本資料型別的變數(int、short、long、byte、float、double、boolean、char等)以及物件的引用變數,其記憶體分配在棧上,變量出了作用域就會自動釋放。
 棧記憶體的主要作用是存放基本資料型別和引用變數。棧的記憶體管理是通過棧的"後進先出"模式來實現的。(主要用來執行程式,存取速度快,大小和生存期必須確定,缺乏靈活性)

Last:以上內容從網路摘抄總結,如有錯誤,歡迎評論交流HooHoo!!!