1. 程式人生 > >JVM運行時數據區--深入理解Java虛擬機 讀後感

JVM運行時數據區--深入理解Java虛擬機 讀後感

出棧 很好 棧幀 最大 出錯 生命周期 所有 img 就會

技術分享

程序計數器

程序計數器是線程私有的區域,很好理解嘛~,每個線程當然得有個計數器記錄當前執行到那個指令。占用的內存空間小,可以把它看成是當前線程所執行的字節碼的行號指示器。如果線程在執行Java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令地址;如果執行的是Native方法,這個計數器的值為空(Undefined)。此內存區域是唯一一個在Java虛擬機規範中沒有規定任何OutOfMemoryError情況的區域。

Java虛擬機棧

與程序計數器一樣,Java虛擬機棧也是線程私有的。其生命周期與線程相同。如何理解虛擬機棧呢?本質上來講,就是個棧。裏面存放的元素叫棧幀,棧幀好像很復雜的樣子,其實它很簡單!它裏面存放的是一個函數的上下文,具體存放的是執行的函數的一些數據。執行的函數需要的數據無非就是局部變量表(保存函數內部的變量)、操作數棧(執行引擎計算時需要),方法出口等等。

執行引擎每調用一個函數時,就為這個函數創建一個棧幀,並加入虛擬機棧。換個角度理解,每個函數從調用到執行結束,其實是對應一個棧幀的入棧和出棧。

註意這個區域可能出現的兩種異常:一種是StackOverflowError,當前線程請求的棧深度大於虛擬機所允許的深度時,會拋出這個異常。制造這種異常很簡單:將一個函數反復遞歸自己,最終會出現棧溢出錯誤(StackOverflowError)。另一種異常是OutOfMemoryError異常,當虛擬機棧可以動態擴展時(當前大部分虛擬機都可以),如果無法申請足夠多的內存就會拋出OutOfMemoryError

本地方法棧

本地方法棧與虛擬機棧所發揮的作用很相似,他們的區別在於虛擬機棧為執行Java代碼方法服務,而本地方法棧是為Native方法服務。與虛擬機棧一樣,本地方法棧也會拋出StackOverflowError和OutOfMemoryError異常。

Java堆

Java堆可以說是虛擬機中最大一塊內存了。它是所有線程所共享的內存區域,幾乎所有的實例對象都是在這塊區域中存放。當然,睡著JIT編譯器的發展,所有對象在堆上分配漸漸變得不那麽“絕對”了。

Java堆是垃圾收集器管理的主要區域。由於現在的收集器基本上采用的都是分代收集算法,所有Java堆可以細分為:新生代和老年代。在細致分就是把新生代分為:Eden空間、From Survivor空間、To Survivor空間。當堆無法再擴展時,會拋出OutOfMemoryError異常。

方法區

方法區存放的是類信息、常量、靜態變量等。方法區是各個線程共享區域,很容易理解,我們在寫Java代碼時,每個線程度可以訪問同一個類的靜態變量對象。由於使用反射機制的原因,虛擬機很難推測那個類信息不再使用,因此這塊區域的回收很難。另外,對這塊區域主要是針對常量池回收,值得註意的是JDK1.7已經把常量池轉移到堆裏面了。同樣,當方法區無法滿足內存分配需求時,會拋出OutOfMemoryError。

制造方法區內存溢出,註意,必須在JDK1.6及之前版本才會導致方法區溢出,原因後面解釋,執行之前,可以把虛擬機的參數-XXpermSize和-XX:MaxPermSize限制方法區大小。

JVM運行時數據區--深入理解Java虛擬機 讀後感