1. 程式人生 > >Java虛擬機系列---Java內存劃分

Java虛擬機系列---Java內存劃分

ica atl ddl san mce dmz aqs ror lpn

Java和C++之間有一堵由內存管理和垃圾收集技術所圍成的“高墻”,墻外的人想進去,墻內的人卻想出來。 ------摘自《深入理解Java虛擬機》

作為一個Java程序員,因為虛擬機的好處,在開發過程中一般不用關心內存分配和垃圾回收方面的內容,這就讓我在跟C++的朋友聊天或溝通的時候,總覺得自己是個假的程序員,雖然我們不用自己動手去做這兩件事情,但還是很有必要去了解一下這方面的原理,這樣萬一真碰到內存溢出的問題,就不至於束手無策了。下面是通過看書總結的一些內容。

一、Java內存區域劃分

Java虛擬機在執行Java程序的過程中,會把它所管理的內存區域劃分成不同的數據區域,沒有數據區域都有各自的功能、創建和銷毀時間,有些隨著虛擬機的啟動而產生,有些隨著用戶線程的創建和結束而產生和銷毀,根據《Java虛擬機規範》的規定,Java虛擬機所管理的內存將會包含下面幾個部分:

技術分享圖片

從上圖可知,Java虛擬機內存主要由線程共享的堆內存、方法區和線程私有的虛擬機棧、本地方法棧和程序計數器五個運行時數據區。

二、各運行時數據區的功能介紹

1、程序計數器

1)程序計數器是當前線程所執行的字節碼的行號指示器,存放下一個要執行的字節碼位置;

2)此內存區域是唯一一個在Java虛擬機規範中沒有任何OutOfMemoryError異常的區域;

3)線程私有

2、Java虛擬機棧

1)Java虛擬機棧是方法執行的內存模型,通俗點說就是執行方法是進行內存管理的區域。

方法執行時,會創建一個棧幀,用於存儲方法中的局部變量、操作數、動態鏈接和方法出口等信息,方法的調用執行過程就是一個棧幀在虛擬機棧中進行入棧出棧的過程;

2)線程私有,隨著線程的開始而創建,線程的結束而銷毀;

3)通常所說的Java棧內存就是指Java虛擬機棧中的局部變量表,它存放了編譯期可知的基本類型(boolean、byte、char、short、int、long、float、dounle)、對象引用和returnAddress類型。局部變量的大小在程序編譯期就已經完成,而且在方法執行期間不會被改變;

4)此區域可能發生的異常有:

StackOverflowError:當線程請求的棧深度超過Java虛擬機所允許的棧深度時,會發生棧溢出異常;

OutOFMemoryError:當虛擬機棧在動態擴展過程中沒有申請到足夠的內存時,會發生內存溢出異常;

3、本地方法棧

1)同虛擬機棧,本地方法棧也是Java方法執行的內存模型,區別在於虛擬機棧是為Java程序在虛擬機中執行服務的,而本地方法棧是為本地方法在Java虛擬機中執行服務的。在虛擬機規範中,對本地方法棧中的方法所使用的語言、使用方法和數據結構都沒有強制規定;

2)線程私有

3)可拋出兩種異常:

StackOverflowError:當線程請求的棧深度超過Java虛擬機所允許的棧深度時,會發生棧溢出異常;

OutOFMemoryError:當虛擬機棧在動態擴展過程中沒有申請到足夠的內存時,會發生內存溢出異常;

4、Java堆

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

2)線程共享,在虛擬機啟動時創建;

3)用來存放對象實例和數組;

4)堆是垃圾收集器管理的主要區域,因此也稱GC堆;

5)堆內存可擴展,可通過參數--Xmx和--Xms來設置最大堆內存和最小堆內存來控制;

6)如果堆中沒有足夠的內存來分配實例,且堆無法擴展時就會拋出OutOfMemoryError異常

5、方法區

1)同堆內存一樣,方法區也是線程共享的內存區域;

2)用來存儲已經被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據;

3)根據Java虛擬機規範,當方法區無法滿足內存分配需求時就會拋出OutOfMemoryError異常

6、直接內存

這部分內存既不是Java虛擬機運行時數據區,也不是Java虛擬機規範中定義的內存區域,但是這部分內存也會被頻繁使用,而且還有可能引起OutOfMemoryError異常。本機內存的分配不會受到Java虛擬機內存分配的影響,但是當虛擬機中各區域的內存之和大於本機內存的話,就會導致動態擴展時出現OutOfMemoryError異常

以上就是Java虛擬機中的內存模型及各內存在程序運行過程中所扮演的角色或所起的作用。下節將會總結各個內存區域出現內存溢出異常的原因和解決方法。

Java虛擬機系列---Java內存劃分