標籤:error flow 強制 執行 overflow 退出 目的 html 動態
Java程式在運行時,需要在記憶體中分配空間。為了提高運行效率,就對資料進行了不同的空間劃分。因為每一片地區都有特定的資料處理方式和記憶體管理方式。
具體分為5種記憶體空間:
程式計數器:保證線程切換後能恢複到原來的執行位置。
虛擬機器棧:(棧記憶體)為虛擬機器執行java方法服務,方法被調用時,建立棧幀-
本地方法棧:為虛擬機器執行使用到的Native方法服務
堆記憶體:存放所有new出來的東西
方法區:儲存被虛擬機器載入的類資訊,常量,靜態常量,靜態方法等。
運行時常量池(方法區的一部分)
GC對他們的回收:
記憶體地區中的程式計數器、虛擬機器棧、本地方法棧這3個地區隨著線程而生,線程而滅;棧中的棧幀隨著方法的進入和退出而有條件的執行出棧和入棧的操作。每個棧幀中分配多少記憶體基本是在類結構確定下來時就已知的。在這個地區不需要過多的考慮回收的問題,因為方法結束或者線程結束時,記憶體自然就跟著回收了。
GC回收的主要對象:Java堆和方法區
一個介面中的多個實作類別需要的記憶體可能不同,一個方法中的多個分支需要的記憶體也可能不一樣,我們只有在程式處於運行期間時才能知道會建立哪些對象,這部分記憶體的分配和回收都是動態,GC關注的也是這部分記憶體。
1.程式計數器:(線程私人)
每隔線程擁有一個程式計數器,線上程建立時建立,指向嚇一跳指令的地址
執行本地方法時,其值為undefined。
說的通俗一點,我們知道,Java是支援多線程的,程式先去執行A線程,執行到一半然後去執行B線程,然後又跑去接著執行A線程,那程式是怎麼記住A線程已經執行到哪裡了呢?這就需要程式計數器了。因此,為了線程切換後能夠恢複到正確執行的位置,每條線程都有一個獨立的程式計數器,這塊屬於“線程私人”的記憶體。
2.Java虛擬機器棧(線程私人)
每隔方法被調用的時候會建立一個棧幀,用於儲存局部變數表,操作棧,動態連結,方法出口等資訊。局部變數表存放的是:編譯器可知的基礎資料型別 (Elementary Data Type),對象參考型別。
每個方法被調用直到執行完的過程,就對應著一個棧幀在虛擬機器中從引入到出棧的過程。
在Java虛擬機器中,對這個地區規定了兩種異常情況:
(1)如果線程請求的棧深度太深,超出了虛擬機器所允許的深度,就會出現StackOverFlowError(比如無線遞迴,因為每一層棧幀都會佔用一定空間,erXss規定了棧的最大空間,超出這個值就會報錯)
(2)虛擬機器棧可以動態擴充,如果擴充到無法申請足夠的記憶體空間,會出現OOM(OutOfMemory)
3.本地方法棧:
(1)本地方法棧與java虛擬機器棧做使用者非常相似,區別是:java虛擬機器棧是為虛擬機器執行java方法服務的而本地方法棧則是為虛擬機器使用到Native方法服務。
(2)Java虛擬機器沒有對本地方法棧的使用和資料結構做強制規定,Sun HotSpot虛擬機器就把java虛擬機器棧和本地方法棧合二為一。
(3)本地方法棧也會拋出StackOverFlowError和OutOfMemoryError
4.Java堆:堆記憶體
(1)堆是Java虛擬機器所管理的記憶體地區中罪的的一塊,java堆是被所有縣城共用的記憶體地區,在java虛擬機器啟動時建立堆記憶體的唯一目的就是存放對象執行個體,幾乎所有的對象執行個體都在堆記憶體配置。
(2)堆是GC管理的主要區域,從記憶體回收的角度看,由於現在的垃圾收集器都是採用的粉黛手機演算法,因此java堆還可以初步細分為新生代和老年代。
(3)Java虛擬機器規定,堆可以處於物理上不連續的記憶體空間中,只要邏輯上連續的即可。在實現的既可以是固定的,也可以是動態擴充的。如果在堆記憶體沒有完成實力分配,並且對大小也無法擴充,就會拋出OutOfMemoryError異常。
5.方法區(線程共用)
(1)用於儲存已被虛擬機器載入的類資訊、常量、靜態變數、即時編譯器編譯後的代碼資料。
(2)Sun HotSpot虛擬機器把方法區叫做永久帶(permanent Generation),方法區中最終要的部分是運行時常量池。
6.運行時常量池:
(1)運行時常量池是方法區的一部分,自然受到方法區記憶體的限制,當常量池無法再申請到記憶體時就會拋出OutOfMemoryError異常。
可以參考http://www.cnblogs.com/smyhvae/p/4748392.html
Java中的記憶體劃分