[三] java虛擬機器 JVM位元組碼 指令集 bytecode 操作碼 指令分類用法 助記符
阿新 • • 發佈:2018-12-27
看起來是非常難以理解的,不妨換一個角度
我們知道區域性變數的空間分配分為兩種long 和 double 佔用2個slot 其他佔用一個
運算元棧,每個單位可以表示虛擬機器支援的任何的一個數據型別
不過運算元棧其實同區域性變數一樣,他也是被組織一個數組, 每個元素的資料寬度和區域性變數的寬度是一致的
所以對於long 和double佔用2個單位長度 對於其他型別佔用一個單位長度
雖然外部呈現上任何一個運算元棧可以表示任何一種資料型別,但是內部是有所區分的
如同區域性變量表使用兩個單位儲存時,訪問元素使用兩個中索引小的那個類似的道理
所以可以把棧理解成線性的陣列,
來一個long或者double 就分配兩個單位空間作為一個元素
其餘型別就分配一個單位空間作為元素
既然棧本身的結構中,線性空間的最小單位的資料寬度同區域性變數,
long和double佔用兩個 也就是下面涉及說到的資料型別的分類1 和 分類2
假設棧的示意結構如下圖所示,(只是給出來一種可能每個元素的型別都可能是隨機的) 左邊表示呈現出來的棧元素 右邊是內部的線性形式 我們當做陣列好了
![image_5b869c5d_3c9b image_5b869c5d_3c9b](https://images2018.cnblogs.com/blog/897393/201808/897393-20180829211943149-1235406783.png)
![image_5b869c5d_24b7 image_5b869c5d_24b7](https://images2018.cnblogs.com/blog/897393/201808/897393-20180829211943632-1601051365.png)
![image_5b869c5d_5c27 image_5b869c5d_5c27](https://images2018.cnblogs.com/blog/897393/201808/897393-20180829211944055-1729354563.png)
![image_5b869c5d_3651 image_5b869c5d_3651](https://images2018.cnblogs.com/blog/897393/201808/897393-20180829211944603-601341154.png)
![image_5b869c5d_7212 image_5b869c5d_7212](https://images2018.cnblogs.com/blog/897393/201808/897393-20180829211945119-1732214990.png)
dup2 可以理解為dup2_x0 插入到他棧頂的內部線性結構的第(2+0)個元素下面 這一次複製的兩個單位array[0] 和 array[1], 到 array[1]下面 可能是對應value1 和value2 表示兩個分類1 也可能是對應一個value1 表示型別為分類2
![image_5b869c5d_3101 image_5b869c5d_3101](https://images2018.cnblogs.com/blog/897393/201808/897393-20180829211945603-1559108988.png)
![image_5b869c5d_6ad0 image_5b869c5d_6ad0](https://images2018.cnblogs.com/blog/897393/201808/897393-20180829211946098-131767083.png)
dup2_x1 插入到他棧頂的內部線性結構的第(2+1)個元素下面 也就是複製array[0] 和 array[1] 到第三個元素 array[2]的下面
array[0] 和 array[1] 可能分別對應value1 和value2 表示兩個分類1 資料 也可能是對應著一個value1表示一個分類2資料
但是array[2] 作為第三個單位,既然能被分割,自然他必須是分類1
所以要麼三個都是分類1,要麼value1 分類2 value2 分類1
![image_5b869c5d_3201 image_5b869c5d_3201](https://images2018.cnblogs.com/blog/897393/201808/897393-20180829211946631-146819796.png)
![image_5b869c5d_3543 image_5b869c5d_3543](https://images2018.cnblogs.com/blog/897393/201808/897393-20180829211947201-1357209470.png)
dup2_x2 插入到他棧頂的內部線性結構的第(2+2)個元素下面 也就是複製array[0] 和 array[1] 到第四個內部元素 array[3]的下面
一次複製兩個,放到第四個下面
這種情形下的組合就非常多了
全都是分類1的資料
![image_5b869c5d_3cea image_5b869c5d_3cea](https://images2018.cnblogs.com/blog/897393/201808/897393-20180829211947693-947355492.png)
全部都是分類2
array[0] 和 array[1] 對應value1 表示一個分類2資料
array[2] 和 array[3] 對應value2 表示一個分類2資料
![image_5b869c5d_5ddd image_5b869c5d_5ddd](https://images2018.cnblogs.com/blog/897393/201808/897393-20180829211948212-905939192.png)
array[0] 和 array[1] 對應value1 表示一個分類2資料 array[2] 和 array[3] 對應value2 和 value3表示兩個分類1資料
![image_5b869c5d_4ebd image_5b869c5d_4ebd](https://images2018.cnblogs.com/blog/897393/201808/897393-20180829211948702-633327856.png)
array[0] 和 array[1] 對應value1 和value2 表示兩個分類1 資料 array[2] 和 array[3] 對應value3表示一個分類2資料
![image_5b869c5d_4ea4 image_5b869c5d_4ea4](https://images2018.cnblogs.com/blog/897393/201808/897393-20180829211949249-557378569.png)
所以說只需要明確以下幾點,就不難理解dup指令
運算元棧指令操作的是棧內部的儲存單元,而不是以一個棧元素為單位的
long和double在棧元素內部需要兩個儲存單元,其餘一個儲存單元
兩個相鄰的內部單位組合起來表示一個棧元素時,是不能拆分的
再回過頭看,所有的dup指令,不過是根據棧元素的實際存放的型別的排列組合,梳理出來的一些複製一個或者兩個棧頂元素的實際操作方式而已
就是因為他是逆向推導的,所以看起來不好理解