JVM内存区域划分及其管理机制
-
程序計數器:是一塊較小的內存空間,它的作用可以看做是當前線程所執行的字節碼的行號指示器。在虛擬機的概念模型里(僅是概念模型,各種虛擬機可能會通過一些更高效的方式去實現),字 節碼解釋器工作時就是通過改變這個計數器的值來選取下一條需要執行的字節碼指令,分支、循環、跳轉、異常處理、線程恢復等基礎功能都需要依賴這個計數器來 完成。
由于Java虛擬機的多線程是通過線程輪流切換并分配處理器執行時間的方式來實現的,在任何一個確定的時刻,一個處理器(對于多核處理器來說是 一個內核)只會執行一條線程中的指令。因此,為了線程切換后能恢復到正確的執行位置,每條線程都需要有一個獨立的程序計數器,各條線程之間的計數器互不影 響,獨立存儲,我們稱這類內存區域為“線程私有”的內存。
如果線程正在執行的是一個Java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令的地址;如果正在執行的是Natvie方法,這個計數器 值則為空(Undefined)。此內存區域是唯一一個在Java虛擬機規范中沒有規定任何OutOfMemoryError情況的區域。
-
方法區:在類裝載器加載class文件到內存的過程中,虛擬機會提取其中的類型信息,并將這些信息存儲到方法區。方法區用于存儲已被虛擬機加載的類信息、常量、靜 態變量、即時編譯器編譯后的代碼等數據。由于所有線程都共享方法區,因此它們對方法區數據的訪問必須被設計為是線程安全的。。在JVM規范中,沒有強制要求方法區必須實現垃圾回收。很多人習慣將方法區稱為“永久代”,是因為HotSpot虛擬機以永久代來實現方法區,從而JVM的垃圾收集器可以像管理堆區一樣管理這部分區域,從而不需要專門為這部分設計垃圾回收機制。垃圾回收器在回收的時候,也僅僅針對常量池和對類型的回收。不過自從JDK7之后,Hotspot虛擬機便將運行時常量池從永久代移除了。
-
java堆:用于存儲java程序創建的對象實例及數組,被所有線程共享,在虛擬機啟動時創建,也是垃圾收集器管理的最主要區域,也稱GC堆。
-
java棧:線程私有,生命周期與線程相同。Java棧也稱作虛擬機棧(Java Vitual Machine Stack),也就是我們常常所說的棧,跟C語言的數據段中的棧類似。事實上,Java棧是Java方法執行的內存模型。為什么這么說呢?下面就來解釋一下其中的原因。
Java棧中存放的是一個個的棧幀,每個棧幀對應一個被調用的方法,在棧幀中包括局部變量表(Local Variables)、操作數棧(Operand Stack)、指向當前方法所屬的類的運行時常量池(運行時常量池的概念在方法區部分會談到)的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些額外的附加信息。當線程執行一個方法時,就會隨之創建一個對應的棧幀,并將建立的棧幀壓棧。當方法執行完畢之后,便會將棧幀出棧。 因此可知,線程當前執行的方法所對應的棧幀必定位于Java棧的頂部。講到這里,大家就應該會明白為什么 在 使用 遞歸方法的時候容易導致棧內存溢出的現象了以及為什么棧區的空間不用程序員去管理了(當然在Java中,程序員基本不用關系到內存分配和釋放的事情,因為 Java有自己的垃圾回收機制),這部分空間的分配和釋放都是由系統自動實施的。對于所有的程序設計語言來說,棧這部分空間對程序員來說是不透明的。下圖 表示了一個Java棧的模型:
局部變量表,是指存放了編譯期間可知的各種基本數據類型(boolean、byte、char、short、int、float、long、double)、對象引用(reference類型)和returnAddress類型(指向了一條字節碼指令的地址)。其中64位長度的long和double類型的數據會占用2個局部變量的空間,其他的只占用1個。局部變量表所需的空間是在編譯時完成分配的,當進入一個方法時,這個方法在幀中分配多大的局部變量空間是完全確定的,因此,在方法運行期間不會改變局部變量表的大小。
操 作數棧,想必學過數據結構中的棧的朋友想必對表達式求值問題不會陌生,棧最典型的一個應用就是用來對表達式求值。想想一個線程執行方法的過程中,實際上就 是不斷執行語句的過程,而歸根到底就是進行計算的過程。因此可以這么說,程序中的所有計算過程都是在借助于操作數棧來完成的。
指向運行時常量池的引用,因為在方法執行的過程中有可能需要用到類中的常量,所以必須要有一個引用指向運行時常量。
方法返回地址,當一個方法執行完畢之后,要返回之前調用它的地方,因此在棧幀中必須保存一個方法返回地址。
由于每個線程正在執行的方法可能不同,因此每個線程都會有一個自己的Java棧,互不干擾。
-
本地方法棧:本地方法棧與Java棧的作用和原理非常相似。區別只不過是Java棧是為執行Java方法服務的,而本地方法棧則是為執行本地方法(Native Method)服務的。在JVM規范中,并沒有對本地方發展的具體實現方法以及數據結構作強制規定,虛擬機可以自由實現它。在HotSopt虛擬機中直接就把本地方法棧和Java棧合二為一。
-
運行時常量池:是方法區的一部分。Class文件中除了有類的版本、字段、方法、接口等描述信息外,還有一項常量池,用于存放編譯期生成的各種字面量和符號引用。
總結
以上是生活随笔為你收集整理的JVM内存区域划分及其管理机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android传感器编程带实例
- 下一篇: 插件框架实现思路及原理