java虛擬機運行時數據區域
java虛擬機內存管理圖
java虛擬機運行時數據區分爲線程共享區和線程獨佔區。
其中線程共享區中包括方法區和java堆;線程獨佔區包括虛擬機棧、本地方法棧、程序計數器。
下面對每部分分別進行解釋:
一、程序計數器:
1.程序計數器是一塊較小的內存空間,它可以看作是當前線程所執行的字節碼的行號指示器。
2.程序計數器處於線程獨佔區。
3.如果線程執行的是java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令的地址。如果正在執行的是 native方法,這個計算器的值爲undefined。
4.此區域是唯一一個在java虛擬機規範中沒有規定任何OutOfMemoryError(內存溢出)情況的區域。
二、java虛擬機棧:
1.虛擬機棧描述的是java方法執行的動態內存模型。
2.棧幀:每個方法執行,都會創建一個棧幀,伴隨着方法從創建到執行完成。
用於存儲局部變量表,操作數棧,動態鏈接,方法出口燈等。
3.局部變量表:存放編譯期可知的各種基本數據類型,引用類型,returnAddress類型。
局部變量表所需要的內存空間在編譯期完成分配,當進入一個方法時,這個方法需要在幀分配多少內存是固定的,在方法運行期間是不會改變局部變量表的大小。
4.大小:虛擬機棧大小有限,如果棧滿了,方法仍然調用,那麼會出現棧內存溢出,StackOverflowError。
如果不指定棧內存大小,方法一直調用,一直去申請棧內存,棧滿了會拋出內存溢出,OutOfMemoryError。
例如:
public class StackTest {
private void test(){
System.out.println("方法執行..");
test();
}
public static void main(String[] args){
new StackTest().test();
}
}
三、本地方法棧:
本地方法棧與虛擬機非常相似。
區別:虛擬機棧爲虛擬機執行java方法服務;本地方法棧爲虛擬機執行native方法服務。
四、Java堆:
存放對象實例;
垃圾收集器管理的主要區域;
新生代,老年代,Eden空間;
如果內存溢出,會拋出OutOfMemoryError異常;
通過-Xmx、-Xms控制大小。
五、方法區:
存儲虛擬機加載的類信息,常量,靜態變量,即時編譯器編譯後的代碼等數據。類信息包括類的版本、字段、方法、接口等。
方法區和永久代。這兩者並不等價。
垃圾回收在方法區的行爲。垃圾回收主要在java堆中,方法區也有比如常量池。
異常的定義。申請失敗會拋出OutOfMemoryError異常
六、運行時常量池:
運行時常量池是方法區的一部分。存放的是編譯器生成的各種字面量和符號引用。
public static void main(String[] args){
String s1 = "abc";//"abc"在常量池中存儲
String s2 = "abc";
System.out.println(s1==s2);//true
String s3 = new String("abc");//new創建的對象在堆中存儲
System.out.println(s1==s3);//flase
//intern方法把值放到常量池中
System.out.println(s1==s3.intern());//true
}
申請內存失敗會拋出OutOfMemoryError異常。
七、直接內存:
直接內存不是虛擬機運行時數據區的一部分,也不是java虛擬機規範中定義的內存區域。但是這部分內存被頻繁的使用,而且可能導致OutOfMemoryError異常。