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