日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

關(guān)于java棧與堆深入了解 對一些錯誤認識的糾正

 風丨瀟瀟 2010-09-26
1. 棧(stack)與堆(heap)都是Java用來在Ram中存放數(shù)據(jù)的地方。與C++不同,Java自動管理棧和堆,程序員不能直接地設(shè)置?;蚨?。
//棧都是由運行環(huán)境來處理的,這點C++和java沒有什么不同.對于堆,不過java多了個GC.
2.這里的堆和棧首先要明確是虛擬機棧,和寄存器根本不是一個級別的東西,就別比較了.
3.棧數(shù)據(jù)共享好像是作者自己創(chuàng)造的概念.而且給基本類型也引入了"引用"的概念,不知道出于何種打算.
java虛擬機規(guī)范中說:Primitive values do not share state with other primitive values. A variable whose type is a primitive type always holds a primitive value of that type.
看一下實際的處理情況:
  int a=3;
  int b=3;
  int c=65535;
  int d=65535;
  int e=32330;
  int f=32330;
看對應(yīng)的虛擬機指令,可以知道變量里實際存儲的是什么:
Code:
  0: iconst_3 //3
  1: istore_1
  2: iconst_3 //3
  3: istore_2
  4: ldc #2; //int 65535
  6: istore_3
  7: ldc #2; //int 65535
  9: istore 4
  11: sipush 32330
  14: istore 5
  16: sipush 32330
  19: istore 6
  21: return
可以看出每個變量保存自己的值.(具體指令的意義參考java虛擬機規(guī)范)
這里要注意的是對于int值,如果它大于short能表示的范圍,則放到常量池中去.
11: sipush 32330
  14: istore 5
這句,11-13,正好是3個字節(jié)的指令大小,一個字節(jié)是sipush指令,2個字節(jié)用來存儲32330這個數(shù).兩次使用到這個數(shù),都是把它直接存給變量的,所以原貼中一直強調(diào)的"棧中共享" 的說法明顯不對.
對于65535,它是大于兩個字節(jié)的,編譯的時候把它放入常量池部分,而把取這個數(shù)的指令寫為ldc#2,我感覺這樣一個直觀的好處是減少了指令代碼的長度.尤其是多次使用到一個相同的數(shù)時.

  其實,java 對變量的處理很簡單,基本類型變量存放值,引用類型存放一個"引用" (實際就是一個"指針" ,以前曾經(jīng)和別人討論過,很多人認為是個"句柄",并舉了很多證據(jù),但是我后來看到了sun的java hotspot白皮書,里面直接說明了,引用實際就是一個c的"指針" ,使用句柄需要多次間接查找,會帶來效率的瓶頸,當然這個指針并不是直接指向?qū)嶋H的對象,實際指向的是一個兩個機器字大小的對象頭,對于數(shù)組是3個機器字大小的對象頭,因為還要保存數(shù)組的長度) .
java設(shè)計時保留基本類型而不把一切都設(shè)計為對象,就是出于效率考慮,如果對于基本類型再通過"引用"去查找值,何苦呢?
4.String也是包裝類? 這應(yīng)該也是作者自己定義了包裝類的概念,去java語言規(guī)范里看看什么是wrapper class.
5.Integer i = 3;編譯器如何處理?
sun的編譯器是這樣處理的:
Integer i=Integer.valueOf(3);
而不是通過new來創(chuàng)建了,因為Integer類中靜態(tài)的創(chuàng)建了-128~+127之間的對象,需要的數(shù)在這個范圍之內(nèi)時,直接返回,此范圍之外的數(shù)才通過new來創(chuàng)建.
簡單測試.
Integer i=3;
Integer j=3;
我們測試i==j會發(fā)現(xiàn)它是true.
String str = new String("abc");去看String類的構(gòu)造方法會發(fā)現(xiàn),這里用的是String(String original)來創(chuàng)建的,也就是說用一個String來創(chuàng)建一個String,"abc"編譯的時候編譯器會把它加入常量池部分.不知道原貼所謂的包裝類是如何得來的.
csdn 的java版有個“推薦”的專門講String常量池的帖子,很不錯。
5."JVM發(fā)現(xiàn)在棧中沒有存放該值的地址,便開辟了這個地址,并創(chuàng)建了一個新的對象,其字符串的值指向這個地址。 "又沒有分清編譯器和虛擬機的職責分配.編譯器會把"abc"放入常量池,并記住它在常量池中的位置,別的地方用到的時候編譯器直接生成ldc指令來制定了,不會讓jvm去找,去開辟地址等等.
7.原貼明顯不知道常量池的存在,好像是把常量池的數(shù)據(jù)都認為是"棧"的了.
  java新增了StringBuilder來處理可變字符串,如果不需要多線程環(huán)境,應(yīng)該首先選擇這個,而不是StringBuffer

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多