JVM(一):Java內存區域與內存溢出異常

一:運行時數據區域

    Java虛擬機在執行Java程序的過程當中會把它所管理的內存劃分爲若干個不一樣的數據區域。而這些區域都有各自的用途,以及建立和銷燬的時間,有的區域隨着虛擬機進程的啓動而存在,有些區域則依賴用戶線程的啓動和結束而創建和銷燬。JVM所管理的內存包括如下幾個運行時數據區域,如圖示:算法

   

1.1    程序計數器(Program Counter Register)

         程序計數器是一塊較小的內存空間,他能夠看做是當前線程所執行的字節碼的行號指示器。其是非線程共享的。        

        若是線程正在執行的是一個Java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令的地址;若是正在執行的是Native方法,這個計數器值則爲空(Undefined)。此內存區域是惟一一個在JVM規範中沒有規定任何OutOfMemoryError狀況的區域。數組

1.2    Java虛擬機棧(Java Virtual Machine   Stack)

        Java虛擬機棧也是線程私有的即非線程共享的。注意:它的生命週期與線程相同學習

        VM Stack描述的是Java方法執行的內存模型,即:spa

                每一個方法在執行的同時都會建立一個棧幀(Stack Frame)用於存儲局部變量表、操做數棧、動態連接、方法出口等信息。每個方法從調用直至執行完成的過程,就對應着一個棧幀在虛擬機棧中入棧道出棧的過程。.net

        局部變量表存放了編譯器可知的各類基本數據類型(boolean、byte、char、short、int、float、long、double)、對象引用(reference類型,它不等同於對象自己,多是一個指向對象起始地址的引用指針,也多是指向一個表明對象的句柄或其餘與此對象相關的位置)和returnAddress類型(指向了一條字節碼指令的地址)。線程

        在JVM規範中,對這個區域規定了兩種異常情況:指針

        1) 若是線程請求的棧深度大於虛擬所容許的深度,將拋出StaOverflowError異常;對象

        2) 若是虛擬機棧能夠動態擴展,若是擴展時沒法申請到足夠的內存,就會拋出OutofMemoryError異常。blog

1.3    本地方法棧(Native Method Stack)

        本地方法棧與虛擬機棧所發揮的做用是很是類似的,一樣其也是非線程共享的。區別是虛擬機棧爲虛擬機執行Java方法服務,而本地方法棧則爲虛擬機使用到的Native方法服務。接口

        與虛擬機棧同樣,本地方法棧區域也會拋出StackOverflowError 和 OutOfMemoryError異常。

1.4    Java 堆(Java Heap)

         Java 堆是Java虛擬機所管理的內存中最大的一塊。

        Java Heap 是被全部線程共享的一塊內存區域,即該區域是線程共享的。在虛擬機啓動時建立。此內存區域的惟一目的就是存放對象實例,幾乎全部的對象實例都在這裏分配內存。在JVM規範中是這樣說的:全部的對象實例以及數組都要在堆上分配,但如今不那麼絕對。注意。

        Java Heap 是垃圾收集器管理的主要區域。而從內存回收的角度看,因爲如今收集器基本都採用分代收集算法,因此Java堆中還能夠細分爲:新生代和老年代;在細緻一點的有Eden空間,From Survivor空間、To Survivor空間等。從內存分配的角度來看,線程共享的Java堆中可能劃分出多個線程私有的分配緩衝區(Thread Local Allocation Buffer ,TLAB)。

不過不管如何劃分,都與存放內容無關,不管是哪一個區域,存儲的都仍然是對象實例。進一步劃分的目的是爲了更好地回收內存,或者更快地分配內存。

        注意:若是在堆中沒有完成實例分配,而且堆也沒法在擴展時,將會拋出OutOfMemoryError異常。

1.5    方法區(Method Area)

         方法區與Java 堆同樣,是各個線程共享的內存區域。它用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。

        注意:當方法區沒法知足內存分配需求時,將拋出OutOfMemoryError異常。

 

總結:

        歸納的說,JVM初始運行的時候都會分配好方法區(Method Area) 和 堆(Heap),而JVM每遇到一個線程,就爲其分配一個程序計數器、虛擬機棧和本地方法棧,當線程終止時,

三者(即程序計數器、虛擬機棧、本地方法棧)所佔用的內存空間也會被釋放掉。這也是爲何把內存區域分爲線程共享和非線程共享的緣由,非線程共享的那三個區域的生命週期與所

屬線程相同,而線程共享的區域與JAVA程序運行的生命週期相同,因此這也是系統垃圾回收的場所只發生在線程共享的區域(實際上大部分只發生在Heap上)的緣由。

 

1.6    運行時常量池(Runtime Constant Pool)

        運行時常量池是方法區的一部分。Class文件中除了有類的版本、字段、方法、接口等描述等信息外,還有一項信息是常量池

(Constant Pool Table),用於存放編譯期生成的各類字面量和符號引用,這部份內容將在類加載後存放到方法區的運行時常量池中存放。

 

1.7    直接內存(Direct Memory)

        直接內存並非虛擬機運行時數據區的一部分,也不是JVM規範中定義的內存區域。可是這部份內存也可能致使OutOfMemoryError異常。                                                                                                                                                                                                                                                                                                                                                                           

關於對象的訪問:

        http://blog.csdn.net/OyangYujun/article/details/41173747

 

更多實戰及內容請學習:

            《深刻理解Java虛擬機》

相關文章
相關標籤/搜索