java 虚拟机内存管理_java虚拟机内存管理
程序計數器:
程序計數器是一塊較小的內存空間,它可以看作是當前線程所執行的字節碼的行號指示器。
程序計數器處于線程獨占區
如果線程執行的是Java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令的地址,如果正在執行的native方法,這個計數器的值為undefined
此區域是唯一一個Java虛擬機規范中沒有規定任何OutOfMenmoryError(內存溢出)情況的區域。
Java虛擬機棧
虛擬機棧描述的是Java方法執行的動態內存模型
棧幀:每個方法執行,都會創建一個棧幀,伴隨這方法從創建到執行完成。用于存儲局部變量表,操作數棧,動態鏈接,方法出口等。
局部變量表:(1).存放編譯期可知的公眾基本數據類型,引用類型,returnAddress類型。 ??????(2).局部變量表的內存空間在編譯期完成分配,當進入一個方法時,這個方法需要在幀分配多少內存是固定的,在方法運行期間是不會改變局部變量表的大小
大小:當棧幀的內存大于Java虛擬機棧的內存時,會報StackOverflowError或OutOfMemoryError內存溢出問題
【示例1-1】:
public static void test(){
test();
}
public static void main(String[] args) {
AssetPreservationServer.test();
}
Java虛擬機棧內存溢出:
Java方法執行動態內存模型圖:
本地方法棧:與Java虛擬機棧的運行都是一致的,唯一的區別是:Java虛擬機棧為虛擬機執行Java方法服務,而本地方法棧為虛擬機執行native方法服務。
Java堆:是虛擬機中管理內存最大的一塊區域。也是垃圾收集器主要的管理區域,主要存放對象實例等等。
方法區:
存儲虛擬機加載的類信息,常量,靜態變量,即時編譯器編譯后的代碼等數據。
類信息包含:類的版本,字段,接口,方法等等。
運行時常量池:
常量池是屬于方法區
代碼【實例1-2】
public static void main(String[] args) {
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//false
System.out.println(s1 == s3.intern());//true
}
運行是常量池運行模型【示例1-3】
解讀:
1.Java中創建兩個變量s1,s2
String s1 = "abc";
String s2?= "abc";
2.程序執行到s1,s2時,Java虛擬機中棧內存開辟一塊局部變量,而這塊局部變量中存放了s1和s2兩個變量
3.堆內存中就創建“abc”,“abc”兩個實例,s1指向一個abc實例,s2指向另外一個“abc”實例
4.我們創建的每一個字符串的都會放到常量池里,所以方法區中就創建了一塊常量池,在常量池中,我們可以想象有一張StringTable表,而它數據類型為一個HashSet集合,用來存放我們所實例化的對象,s1創建一個“abc”,就會放到HashSet中,創建一個就存放一個,而HashSet的特性是無序不可重復的,所以s1和s2創建的“abc”最后只存放了一個“abc”,所以s1和s2的對應地址顯然是相同的(s1==s2的值是相等的)
5.再創建一個實例s3
String s3 = new String("abc");
6.第5步創建的實例是我們手動直接創建,我們通過new創建出來的對象是直接放在堆內存里,所以就不用去考慮常量池的問題了。就直接在堆內存中開辟一塊空間,將值直接賦給了s3,所以s3==s1或s2時,值是false的
7.當我們在s3加intern()方法時,s1==s3.intern()的值為true,因為intern()這個方法會把我們創建的“abc”區域,搬到運行時常量池里面去,產生一個運行時常量,所以s1==s3.intern()的值是true。
總結
以上是生活随笔為你收集整理的java 虚拟机内存管理_java虚拟机内存管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ZZULIOJ 1115: 数组最小值
- 下一篇: 程序员常见保健方法【转贴】