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