http://blog.csdn.net/u010425776/article/details/51170118
java虛擬機(jī)(Java Virtual Machine=JVM)的內(nèi)存空間分為五個(gè)部分,分別是: 1. 程序計(jì)數(shù)器 2. Java虛擬機(jī)棧 3. 本地方法棧 4. 堆 5. 方法區(qū)。
下面對(duì)這五個(gè)區(qū)域展開(kāi)深入的介紹。
程序計(jì)數(shù)器是一塊較小的內(nèi)存空間,可以把它看作當(dāng)前線程正在執(zhí)行的字節(jié)碼的行號(hào)指示器。也就是說(shuō),程序計(jì)數(shù)器里面記錄的是當(dāng)前線程正在執(zhí)行的那一條字節(jié)碼指令的地址。 注:但是,如果當(dāng)前線程正在執(zhí)行的是一個(gè)本地方法,那么此時(shí)程序計(jì)數(shù)器為空。
程序計(jì)數(shù)器有兩個(gè)作用:
字節(jié)碼解釋器通過(guò)改變程序計(jì)數(shù)器來(lái)依次讀取指令,從而實(shí)現(xiàn)代碼的流程控制,如:順序執(zhí)行、選擇、循環(huán)、異常處理。在多線程的情況下,程序計(jì)數(shù)器用于記錄當(dāng)前線程執(zhí)行的位置,從而當(dāng)線程被切換回來(lái)的時(shí)候能夠知道該線程上次運(yùn)行到哪兒了。Java虛擬機(jī)棧是描述Java方法運(yùn)行過(guò)程的內(nèi)存模型。 Java虛擬機(jī)棧會(huì)為每一個(gè)即將運(yùn)行的Java方法創(chuàng)建一塊叫做“棧幀”的區(qū)域,這塊區(qū)域用于存儲(chǔ)該方法在運(yùn)行過(guò)程中所需要的一些信息,這些信息包括:
局部變量表 存放基本數(shù)據(jù)類型變量、引用類型的變量、returnAddress類型的變量。操作數(shù)棧動(dòng)態(tài)鏈接方法出口信息等當(dāng)一個(gè)方法即將被運(yùn)行時(shí),Java虛擬機(jī)棧首先會(huì)在Java虛擬機(jī)棧中為該方法創(chuàng)建一塊“棧幀”,棧幀中包含局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、方法出口信息等。當(dāng)方法在運(yùn)行過(guò)程中需要?jiǎng)?chuàng)建局部變量時(shí),就將局部變量的值存入棧幀的局部變量表中。 當(dāng)這個(gè)方法執(zhí)行完畢后,這個(gè)方法所對(duì)應(yīng)的棧幀將會(huì)出棧,并釋放內(nèi)存空間。
注意:人們常說(shuō),Java的內(nèi)存空間分為“棧”和“堆”,棧中存放局部變量,堆中存放對(duì)象。 這句話不完全正確!這里的“堆”可以這么理解,但這里的“?!敝淮砹薐ava虛擬機(jī)棧中的局部變量表部分。真正的Java虛擬機(jī)棧是由一個(gè)個(gè)棧幀組成,而每個(gè)棧幀中都擁有:局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、方法出口信息。
注:StackOverFlowError和OutOfMemoryError的異同? StackOverFlowError表示當(dāng)前線程申請(qǐng)的棧超過(guò)了事先定好的棧的最大深度,但內(nèi)存空間可能還有很多。 而OutOfMemoryError是指當(dāng)線程申請(qǐng)棧時(shí)發(fā)現(xiàn)棧已經(jīng)滿了,而且內(nèi)存也全都用光了。
本地方法棧和Java虛擬機(jī)棧實(shí)現(xiàn)的功能類似,只不過(guò)本地方法區(qū)是本地方法運(yùn)行的內(nèi)存模型。
本地方法被執(zhí)行的時(shí)候,在本地方法棧也會(huì)創(chuàng)建一個(gè)棧幀,用于存放該本地方法的局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、出口信息。
方法執(zhí)行完畢后相應(yīng)的棧幀也會(huì)出棧并釋放內(nèi)存空間。
也會(huì)拋出StackOverFlowError和OutOfMemoryError異常。
堆是用來(lái)存放對(duì)象的內(nèi)存空間。 幾乎所有的對(duì)象都存儲(chǔ)在堆中。
Java虛擬機(jī)規(guī)范中定義方法區(qū)是堆的一個(gè)邏輯部分。 方法區(qū)中存放已經(jīng)被虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等。
方法區(qū)中存放三種數(shù)據(jù):類信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼。其中常量存儲(chǔ)在運(yùn)行時(shí)常量池中。
我們一般在一個(gè)類中通過(guò)public static final來(lái)聲明一個(gè)常量。這個(gè)類被編譯后便生成Class文件,這個(gè)類的所有信息都存儲(chǔ)在這個(gè)class文件中。
當(dāng)這個(gè)類被Java虛擬機(jī)加載后,class文件中的常量就存放在方法區(qū)的運(yùn)行時(shí)常量池中。而且在運(yùn)行期間,可以向常量池中添加新的常量。如:String類的intern()方法就能在運(yùn)行期間向常量池中添加字符串常量。
當(dāng)運(yùn)行時(shí)常量池中的某些常量沒(méi)有被對(duì)象引用,同時(shí)也沒(méi)有被變量引用,那么就需要垃圾收集器回收。
直接內(nèi)存是除Java虛擬機(jī)之外的內(nèi)存,但也有可能被Java使用。
在NIO中引入了一種基于通道和緩沖的IO方式。它可以通過(guò)調(diào)用本地方法直接分配Java虛擬機(jī)之外的內(nèi)存,然后通過(guò)一個(gè)存儲(chǔ)在Java堆中的DirectByteBuffer對(duì)象直接操作該內(nèi)存,而無(wú)需先將外面內(nèi)存中的數(shù)據(jù)復(fù)制到堆中再操作,從而提升了數(shù)據(jù)操作的效率。
直接內(nèi)存的大小不受Java虛擬機(jī)控制,但既然是內(nèi)存,當(dāng)內(nèi)存不足時(shí)就會(huì)拋出OOM異常。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注