LetsCoding.cn

          天地之間有桿秤,拿秤砣砸老百姓。

          對象和數組:JVM中,處理對象和數組的字節碼介紹

          歡迎來到“Under The Hood”第五期。本期我們來看看JVM中處理對象和數組的字節碼。你可能需要閱讀往期的文章才能更好的理解本文。

          面向對象的機器

          JVM中的數據有3種形式:對象(object),對象引用(object reference)和原始類型(primitive type)。對象存放在垃圾收集堆中;對象引用和原始類型,根據它們作用域范圍的不同,分別存放在不同的地方:作為本地變量,存放在Java棧中;作為實例變量,存放在垃圾收集堆上;作為類變量,存放在方法區上。

          在JVM中,垃圾收集堆上只能給對象分配內存空間。原始類型,除了作為對象的一部分,沒有其他方式可以給它在堆上分配空間。在需要對象引用的地方,如果你想使用原始類型,你可以給原始類型分配java.lang包中相應的包裝對象。只有對象引用和原始類型可以作為本地變量,存放在Java棧中,對象是不可能存放在棧中的。

          JVM中,對象和原始類型在架構上的分離,體現在Java編程語言中就是:對象不能被聲明成本地變量,只有對象引用才行。在聲明時,對象引用不會指向具體對象,只有引用被顯式的初始化之后(指向已存在對象,或者通過new關鍵字創建新對象),引用才會指向實際對象。

          在JVM指令集中,除了數組,所有的對象都通過相同的操作符集來實例化和訪問。在Java中,數組也是對象,并且就像Java程序中任何其他對象一樣,是動態創建的。數組引用可以用在任何需要Object類型的引用的地方,Object中的任何方法,都可以在數組上調用。但是,在JVM里,數組是使用有別于對象的特殊字節碼來處理的。

          就像任何其他對象一樣,數組不能被聲明為本地變量;只有數組引用可以。數組對象本身,總是包含一組原始類型或者一組對象引用。如果你聲明一個對象數組,你會得到一組對象引用。對象們自己必須用new顯式創建,并被賦值給數組的元素。

          處理對象的字節碼

          實例化新對象是通過操作碼new來實現的,它需要2個單字節的操作數。這2個單字節操作數合并成16位的常量池索引。常量池中對應的元素給出了新對象的類型信息。就像下面所展示的,JVM在堆上創建新的對象實例,并把它的引用壓入棧中。


          OPCODE
          OPERAND(S)
          DESCRIPTION
          new indexbyte1, indexbyte2 creates a new object on the heap, pushes reference

          接下來的表格,列出了存取對象字段(field)的字節碼。操作符putfield和getfield只負責處理實例變量。靜態變量使用putstatic和getstatic訪問,這個我們待會再說。操作符putfield和getfield都有2個單字節操作數,它們合并成16位的常量池索引。相應的常量池位置上存放著關于字段的類型,大小和偏移量的信息。putfield和getfield都會從棧中取得操作對象的引用。putfield從棧上獲取所要賦給實例變量的值,而getfield則把取到的實例變量的值壓進棧中。


          OPCODE
          OPERAND(S)
          DESCRIPTION
          putfield indexbyte1, indexbyte2 set field, indicated by index of object to value (both taken from stack)
          getfield indexbyte1, indexbyte2 pushes field, indicated by index of object (taken from stack)

          如下表所示,靜態變量通過putstatic和getstatic來訪問。它們所擁有的2個單字節的操作數,會由JVM合并成16位的常量池索引。對應的常量池位置上存有靜態變量的相關信息。由于靜態變量不跟任何對象關聯,putstatic和getstatic也不會使用對象引用。putstatic從棧中取得所要附給靜態變量的值,而getstatic則把靜態變量的值壓入棧中。


          OPCODE
          OPERAND(S)
          DESCRIPTION
          putstatic indexbyte1, indexbyte2 set field, indicated by index, of object to value (both taken from stack)
          getstatic indexbyte1, indexbyte2 pushes field, indicated by index, of object (taken from stack)

          下面的操作碼用來檢查棧頂的對象引用,是不是指向由操作數所索引的類或接口的實例。

          當對象不是指定類或接口的實例時,checkcast指令會拋出CheckCastException異常;反之,checkcast什么也不做,對象引用仍保留在棧頂,繼續執行下一個指令。checkcast指令保證了運行時的類型轉換是安全的,它是JVM安全系統的一部分。

          instanceof指令彈出棧頂的對象引用,最后把true或false壓入棧中。如果對象確實是指定類或接口的實例,則把true入棧;反之,false入棧。instanceof指令實現了Java語言中的instanceof關鍵字,它允許程序員測試一個對象是不是某個類或接口的實例。


          OPCODE
          OPERAND(S)
          DESCRIPTION
          checkcast indexbyte1, indexbyte2 Throws ClassCastException if objectref on stack cannot be cast to class at index
          instanceof indexbyte1, indexbyte2 Pushes true if objectref on stack is an instanceof class at index, else pushes false

          處理數組的字節碼

          可以通過指令newarray,anewarray,和multianewarray實例化數組。

          newarray用來創建原始類型的數組,具體類型由它的單字節操作數指定。它可以創建的數組類型有byte,short,char,int,long,float,double和boolean。

          anewarray創建對象引用數組,它的2個單字節操作數合并成16位常量池索引,由此獲取到要創建的包含在數組中的對象類型信息。anewarray為數組中的對象引用分配控件,并把它們都設置為null。

          multianewarray用來分配多維數組(數組的數組),可以通過重復調用newarray和anewarray來實現。multianewarray指令只是簡單的把創建多維數組的多條字節碼壓縮成一個指令。它的開頭2個單字節操作數合并成常量池索引,由此獲取多維數組中的對象類型。第3個單字節操作數指明了多維數組的維數。至于每維的數組大小需從棧上獲取。該指令為多維數組中所有的數組分配空間。


          OPCODE
          OPERAND(S)
          DESCRIPTION
          newarray atype pops length, allocates new array of primitive types of type indicated by atype, pushes objectref of new array
          anewarray indexbyte1, indexbyte2 pops length, allocates a new array of objects of class indicated by indexbyte1 and indexbyte2, pushes objectref of new array
          multianewarray indexbyte1, indexbyte2, dimensions pops dimensions number of array lengths, allocates a new multidimensional array of class indicated by indexbyte1 and indexbyte2, pushes objectref of new array

          下表列出的指令把棧頂的數組引用彈出,把它的長度壓入棧中。


          OPCODE
          OPERAND(S)
          DESCRIPTION
          arraylength (none) pops objectref of an array, pushes length of that array

          下面的操作碼獲取數組中的元素。數組索引和數組引用從棧上彈出,數組中指定索引處的值被壓入棧中。


          OPCODE
          OPERAND(S)
          DESCRIPTION
          baload (none) pops index and arrayref of an array of bytes, pushes arrayref[index]
          caload (none) pops index and arrayref of an array of chars, pushes arrayref[index]
          saload (none) pops index and arrayref of an array of shorts, pushes arrayref[index]
          iaload (none) pops index and arrayref of an array of ints, pushes arrayref[index]
          laload (none) pops index and arrayref of an array of longs, pushes arrayref[index]
          faload (none) pops index and arrayref of an array of floats, pushes arrayref[index]
          daload (none) pops index and arrayref of an array of doubles, pushes arrayref[index]
          aaload (none) pops index and arrayref of an array of objectrefs, pushes arrayref[index]

          下表列出了把值存入數組元素中的操作碼。值、索引和數組引用均從棧頂彈出。


          OPCODE
          OPERAND(S)
          DESCRIPTION
          bastore (none) pops value index, and arrayref of an array of bytes, assigns arrayref[index] = value
          castore (none) pops value index, and arrayref of an array of chars, assigns arrayref[index] = value
          sastore (none) pops value index, and arrayref of an array of shorts, assigns arrayref[index] = value
          iastore (none) pops value index, and arrayref of an array of ints ,assigns arrayref[index] = value
          lastore (none) pops value index, and arrayref of an array of longs, assigns arrayref[index] = value
          fastore (none) pops value index, and arrayref of an array of floats, assigns arrayref[index] = value
          dastore (none) pops value index, and arrayref of an array of doubles, assigns arrayref[index] = value
          aastore (none) pops value index, and arrayref of an array of objectrefs, assigns arrayref[index] = value

          本文譯自:Objects and Arrays

          原創文章,轉載請注明: 轉載自碼農合作社
          本文鏈接地址: 對象和數組:JVM中,處理對象和數組的字節碼介紹

          posted on 2014-05-30 02:14 Rolandz 閱讀(1347) 評論(1)  編輯  收藏 所屬分類: 編程實踐

          評論

          # re: 對象和數組:JVM中,處理對象和數組的字節碼介紹 2014-06-13 00:12 泡菜

          每一次來這里都會有收獲。  回復  更多評論   

          導航

          統計

          留言簿(1)

          隨筆分類(12)

          隨筆檔案(19)

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: SHOW| 长乐市| 湖南省| 拜泉县| 星座| 来宾市| 新绛县| 井研县| 杭锦后旗| 巩义市| 宣威市| 兴义市| 昌吉市| 石嘴山市| 依安县| 榆树市| 慈溪市| 邯郸县| 庄浪县| 金昌市| 冕宁县| 邳州市| 镇康县| 大丰市| 清涧县| 嘉鱼县| 龙井市| 鹤庆县| 集贤县| 上蔡县| 台北县| 余江县| 荣昌县| 股票| 宜春市| 南平市| 玉山县| 肥城市| 犍为县| 宜州市| 平和县|