免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Java中的棧,堆,方法區(qū)和常量池

 要說(shuō)Java中的棧,堆,方法區(qū)和常量池就要提到HotSpot,HotSpot是Sun JDK 和 Open JDK中所帶的虛擬機(jī)。   (Sun JDK 和 Open JDK除了注釋不同,代碼實(shí)現(xiàn)基本上是一樣的)

以下說(shuō)的內(nèi)容都是圍繞HotSpot。

 

Stack(棧):分為VM Stack(虛擬機(jī)棧)和Native Method Stack(本地方法棧),不過(guò)HotSpot虛擬機(jī)直接把本地方法棧和虛擬機(jī)棧合二為一了。 

                  虛擬機(jī)棧: 線程私有的, 描述的是Java方法執(zhí)行的內(nèi)存模型,方法調(diào)用的同時(shí)創(chuàng)建一個(gè)棧幀(儲(chǔ)存局部變量表,操作數(shù)棧,方法出口等等),每個(gè)方法的調(diào)用直到執(zhí)行完成對(duì)應(yīng)的是棧幀在虛擬機(jī)中入棧和出棧的過(guò)程。                              

局部變量表(通常說(shuō)的棧其實(shí)是棧里面的局部變量表):存放基本數(shù)據(jù)類型變量和對(duì)象的引用(所需內(nèi)存在編譯時(shí)期完成分配,方法運(yùn)行時(shí)期不改變局部變量表大小,四個(gè)字節(jié)占用一個(gè)局部變量空間)

 --------棧中的數(shù)據(jù)可以共享:

             int a = 3; 
             int b = 3; 
   編譯器先處理int a = 3;首先它會(huì)在棧中創(chuàng)建一個(gè)變量為a的引用,然后查找棧中是否有3這個(gè)值,如果沒(méi)找到,就將3存放 進(jìn)來(lái),然后將a指向3。接著  處理int b = 3;在創(chuàng)建完b的引用變量后,因?yàn)樵跅V幸呀?jīng)有3這個(gè)值,便將b直接指向3。這樣,就出現(xiàn)了a與b同時(shí)均指向3的情況。這時(shí),如果再令  a=4;那么編譯器會(huì)重新搜索棧中是否有4值,如果沒(méi)有,則將4存放進(jìn)來(lái),并令a指向4;如果已經(jīng)有了,則直接將a指向這個(gè)地址。因此a值的改變不  會(huì)影響到b的值。要注意這種數(shù)據(jù)的共享與兩個(gè)對(duì)象的引用同時(shí)指向一個(gè)對(duì)象的這種共享是不同的,因?yàn)檫@種情況a的修改并不會(huì)影響到b, 它是由編譯  器完成的,它有利于節(jié)省空間。而一個(gè)對(duì)象引用變量修改了這個(gè)對(duì)象的內(nèi)部狀態(tài),會(huì)影響到另一個(gè)對(duì)象引用變量。 

包裝類數(shù)據(jù),如Integer, String, Double等將相應(yīng)的基本數(shù)據(jù)類型包裝起來(lái)的類。這些類數(shù)據(jù)全部存在于堆中,Java用new()語(yǔ)句來(lái)顯示地告訴編譯器,在運(yùn)行時(shí)才根據(jù)需要?jiǎng)討B(tài)創(chuàng)建,因此比較靈活,但缺點(diǎn)是要占用更多的時(shí)間。

==比較的是對(duì)象的地址,也就是是否是同一個(gè)對(duì)象;

equal比較的是對(duì)象的值。

int 變?yōu)镮nteger 時(shí)  如果值在-128~127之間  則不會(huì)創(chuàng)建新的integer對(duì)象 儲(chǔ)存常量池中,這么做的目的是提高效率----->記得在別的地方看過(guò)不知道對(duì)不對(duì)


Java代碼  
public class Test {    
    public static void main(String[] args)    
    {  int a1=1;  
        int b1=1;  
        int c1=2;  
        int d1=a1 b1;  
        Integer a = 1;    
        Integer b = 2;    
        Integer c = 3;    
        Integer d = 3;    
        Integer e = 321;    
        Integer f = 321;    
        Long g = 3L;    
        System.out.println(a1==b1);   //true  結(jié)果1    
        System.out.println(c1==d1);   //true  結(jié)果2  
        System.out.println(c==d);   //true  結(jié)果3     
        System.out.println(e==f);   //false  結(jié)果4       
    }    
}    
 分析:結(jié)果1:a1==b1如上面所述,會(huì)在棧 中開辟存儲(chǔ)空間存放數(shù)據(jù)。
          結(jié)果2:首先它會(huì)在棧 中創(chuàng)建一個(gè)變量為c1的引用,然后查找有沒(méi)有字面值為2的地址,沒(méi)找到,就開辟一個(gè)存放2這個(gè)字面值的地址,然后將c1指向2的地址,d1為兩個(gè)字面值相加也為2, 由于在棧中已經(jīng)有2這個(gè)字面值,便將d1直接指向2的地址。這樣,就出現(xiàn)了c1與d1同時(shí)均指向3的情況。
 
        在分析下面結(jié)果以前讓我們先對(duì)Java自動(dòng)拆箱和裝箱做個(gè)了結(jié):在自動(dòng)裝箱時(shí),把int變成Integer的時(shí)候,是有規(guī)則的,當(dāng)你的int的值在-128-IntegerCache.high(127) 時(shí),返回的不是一個(gè)新new出來(lái)的Integer對(duì)象,而是一個(gè)已經(jīng)緩存在堆 中的Integer對(duì)象,(我們可以這樣理解,系統(tǒng)已經(jīng)把-128到127之 間的Integer緩存到一個(gè)Integer數(shù)組中去了,如果你要把一個(gè)int變成一個(gè)Integer對(duì)象,首先去緩存中找,找到的話直接返回引用給你就 行了,不必再新new一個(gè)),如果不在-128-IntegerCache.high(127) 時(shí)會(huì)返回一個(gè)新new出來(lái)的Integer對(duì)象。
 
         結(jié)果3:由于3是在范圍內(nèi)所以是從緩存中取數(shù)據(jù)的,c和d指向同一個(gè)對(duì)象,結(jié)果為true;
         結(jié)果4:由于321不是在范圍內(nèi)所以不是從緩存中取數(shù)據(jù)的而是單獨(dú)有new對(duì)象,e和f并沒(méi)有指向同一個(gè)對(duì)象,結(jié)果為false;

JAVA堆:

Java堆是被所有線程共享的一塊區(qū)域,在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建 ,此內(nèi)存的唯一目的就是存放對(duì)象實(shí)例和數(shù)組   GC 管理的主要區(qū)域。

分為新生代(Eden Survivor Survivor8:1:1)和老年代

Java堆可以處于物理上不連續(xù)的內(nèi)存空間中,只要邏輯連續(xù)即可

關(guān)于對(duì)象的創(chuàng)建請(qǐng)參考:http://note.youdao.com/yws/public/redirect/share?id=5177014ee5ad1ac3f0af9fdab3b011a3&type=false
關(guān)于GC回收請(qǐng)參考:http://note.youdao.com/yws/public/redirect/share?id=96928e82082b4dec8831e5099769172b&type=false

 

方法區(qū):

            不等價(jià)于永久代hotspot用永久代實(shí)現(xiàn)方法區(qū)(在jdk1.7的HotSpot中 已經(jīng)把原本放在永久代中的字符串常量池移出
              與堆一樣是線程共享的一塊內(nèi)存區(qū)域。
              用于儲(chǔ)存已被虛擬機(jī)加載的信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。
             垃圾收集行為在方法區(qū)很少出現(xiàn),這塊區(qū)域回收的主要目標(biāo)是針對(duì)常量池的回收和對(duì)類型的卸載            

 

運(yùn)行時(shí)常量池:

                       方法區(qū)的一部分
                       常量池用于存放編譯期生成的各種字面量符號(hào)引用(還有翻譯出來(lái)的直接引用),這部分內(nèi)容在類加載后進(jìn)入方法區(qū)的運(yùn)行時(shí)常量池中存放。 
                       運(yùn)行時(shí)常量池相對(duì)于Class文件常量池的另一個(gè)重要特征是具備動(dòng)態(tài)性,運(yùn)行期間也可能將新的常量放入池中

             字面量:如文本字符串,聲明為final的常量值等。

                                       public stick final int i =3;

                                                    String s='abc';

                 符號(hào)引用:類和接口的全限定名 

                                          字段的名稱和描述符

                                方法的名稱和描述符

 

String 的本質(zhì)是字符數(shù)組。 
String 的標(biāo)準(zhǔn)實(shí)現(xiàn)含有4個(gè)實(shí)例變量 
                                        指向字符數(shù)組的引用       
                                        int類型    偏移量
                                        int類型    字符串的長(zhǎng)度
                                        int類型     散列值

public class String{
      private char[]value;
      private int offset;
      private int count;
      private int hash;
...
}

一個(gè)String對(duì)象總共使用40字節(jié)(16字節(jié)對(duì)象本身開銷 8字節(jié)的引用 三個(gè)int類型(12字節(jié)) 4字節(jié)(填充字節(jié))),因?yàn)镾tring的char數(shù)組常常是在多個(gè)字符串之間共享的,因此String對(duì)象是不可變的

String是一個(gè)特殊的包裝類數(shù)據(jù)。即可以用String str = new String('abc');的形式來(lái)創(chuàng)建,也可以用String str = 'abc';的形式來(lái)創(chuàng)建

String str = 'abc'創(chuàng)建對(duì)象的過(guò)程
1 首先在常量池中查找是否存在內(nèi)容為'abc'字符串對(duì)象
2 如果不存在則在常量池中創(chuàng)建'abc',并讓str引用該對(duì)象
3 如果存在則直接讓str引用該對(duì)象


至 于'abc'是怎么保存,保存在哪?常量池屬于類信息的一部分,而類信息反映到JVM內(nèi)存模型中是對(duì)應(yīng)存在于JVM內(nèi)存模型的方法區(qū),也就是說(shuō)這個(gè)類信息 中的常量池概念是存在于在方法區(qū)中,而方法區(qū)是在JVM內(nèi)存模型中的堆中由JVM來(lái)分配的,所以'abc'可以說(shuō)存在于堆中(而有些資料,為了把方法區(qū)的 堆區(qū)別于JVM的堆,把方法區(qū)稱為棧)。一般這種情況下,'abc'在編譯時(shí)就被寫入字節(jié)碼中,所以class被加載時(shí),JVM就為'abc'在常量池中 分配內(nèi)存,所以和靜態(tài)區(qū)差不多。
4(2)String str = new String('abc')創(chuàng)建實(shí)例的過(guò)程
1 首先在堆中(不是常量池)創(chuàng)建一個(gè)指定的對(duì)象'abc',并讓str引用指向該對(duì)象
2 在字符串常量池中查看,是否存在內(nèi)容為'abc'字符串對(duì)象
3 若存在,則將new出來(lái)的字符串對(duì)象與字符串常量池中的對(duì)象聯(lián)系起來(lái)
4 若不存在,則在字符串常量池中創(chuàng)建一個(gè)內(nèi)容為'abc'的字符串對(duì)象,并將堆中的對(duì)象與之聯(lián)系起來(lái)

String str1 = 'abc'; String str2 = 'ab' 'c'; str1==str2是ture
是因?yàn)镾tring str2 = 'ab' 'c'會(huì)查找常量池中時(shí)候存在內(nèi)容為'abc'字符串對(duì)象,如存在則直接讓str2引用該對(duì)象,顯然String str1 = 'abc'的時(shí)候,上面說(shuō)了,會(huì)在常量池中創(chuàng)建'abc'對(duì)象,所以str1引用該對(duì)象,str2也引用該對(duì)象,所以str1==str2
String str1 = 'abc'; String str2 = 'ab'; String str3 = str2 'c'; str1==str3是false                ---------//可參考Java編程思想第四版P284,285
是因?yàn)镾tring str3 = str2 'c'涉及到變量(不全是常量)的相加,所以會(huì)生成新的對(duì)象,其內(nèi)部實(shí)現(xiàn)是先new一個(gè)StringBuilder,然后 append(str2),append('c');然后讓str3引用toString()返回的對(duì)象

 

 

 

    String s = new String(“abc”); 產(chǎn)生幾個(gè)對(duì)象?

    一個(gè)或兩個(gè),如果常量池中原來(lái)沒(méi)有 ”abc”, 就是兩個(gè)(參考棧中的數(shù)據(jù)共享)。

 



本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
面試題之String str = new String(“abc”); 創(chuàng)建了幾個(gè)對(duì)象
Java之內(nèi)存分析和String對(duì)象
癡情研究java內(nèi)存中的對(duì)象
javaSE中的==和equals的聯(lián)系與區(qū)別
關(guān)于Java棧與堆的思考
Java字符串(String)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服