java虚拟机指令初步学习
先做一個最簡程序;然后反匯編一下;
public class hello {public static void main(String[] args) { int a = 101;} }然后來學習幾個jvm的基本指令;
第一條是aload_0,似乎每個java控制臺程序反匯編了都是這句;
aload_<n>
? ? 從局部變量表加載一個reference類型值到操作數棧中;
? ? <n>代表當前棧幀中局部變量表的索引值;
然后是invokespecial #1;
invokespecial:用于調用一些需要特殊處理的實例方法、包括實例初始化方法、私有方法和父類方法;
java.lang.object;Object類是所有Java類的祖先;
那么這句是本程序的類實例的初始化;
?
int a = 101;
反匯編后一共有2句;
bipush? ? ? ? 101
istore_1
bipush
? ? 將一個byte類型數據入棧;
? ? 格式:bipush byte
? ? 將立即數byte帶符號擴展為一個int類型的值value,然后將value入棧到操作數棧中;
istore_<n>
? ? 將一個int類型數據保存到本地變量表中;
? ? <n>必須是一個指向當前棧幀局部變量表的索引值;
也就是把101入棧到操作數棧,然后放入本地變量表;因為代碼中定義的 a 是一個本地變量;
初步認識是,虛擬機指令是一種類匯編的語言,它有加載和存儲指令;
加載和存儲指令用于將數據在棧幀中的局部變量表和操作數棧之間來回傳輸;
匯編MOV指令是數據傳送指令,在寄存器和內存地址之間傳送數據;虛擬機的加載和存儲指令是在局部變量表和操作數棧之間傳送數據;
局部變量表,操作數棧,這些是JVM運行時定義的一些內存區域;
再看一個;
public class hello2 {public static void main(String[] args) { int a11 = -2147483647;System.out.println(a11);int a16 = -32769;System.out.println(a16);int a07 = 32768;int a08 = 65535;int a09 = 65536;int a10 = 2147483647;System.out.println(a10);} }對class反匯編后如下;
用到的相關指令如下;
bipush
? ? 將一個byte類型數據入棧;
? ? 格式:bipush byte
? ? 將立即數byte帶符號擴展為一個int類型的值value,然后將value入棧到操作數棧中;
istore_<n>
? ? 將一個int類型數據保存到本地變量表中;
? ? <n>必須是一個指向當前棧幀局部變量表的索引值;
ldc
? ? 從運行時常量池中提取數據并壓入操作數棧;
? ? 格式:ldc index
? ? index是一個無符號byte類型數據,用作當前類的運行時常量池的索引;
getstatic
? ? 獲取類的靜態字段值;
? ? 格式:getstatic indexbyte1 indexbyte2
? ? indexbyte1和indexbyte2用于構建一個指向當前類的運行時常量池的索引值;
? ??
iload_<n>
? ? 從局部變量表加載一個int類型值到操作數棧中;
? ? <n>代表一個當前棧幀中局部變量表的索引值;
invokevirtual:用于調用對象的實例方法,根據對象的實際類型進行分派(虛方法分派),這也是Java語言中最常見的方法分派方式;
?
一開始是ldc,從反匯編代碼看,自己程序給出的數值,像?int a07 = 32768 這樣的,32768這些值被放入了運行時常量池;當要用到時把數據壓入操作數棧;
然后是istore;把值保存到本地變量表;
然后getstatic,不了解;
運行時常量池,是JVM運行時定義的一個內存區域;
然后是iload;把數值加載到操作數棧;
然后是invokevirtual;這就是調用println方法了;
不是很了解;先看一下吧;
?
運行時常量池簡介
運行時常量池(Runtime Constant Pool),它是方法區的一部分。Class文件中除了有類的版本、字段、方法、接口等描述等信息外,還有一項信息是常量池(Constant Pool Table),用于存放編譯期生成的各種字面量和符號引用,這部分內容將在類加載后存放到常量池中。
運行時常量是相對于常量來說的,它具備一個重要特征是:動態性。當然,值相同的動態常量與我們通常說的常量只是來源不同,但是都是儲存在池內同一塊內存區域。Java語言并不要求常量一定只能在編譯期產生,運行期間也可能產生新的常量,這些常量被放在運行時常量池中。這里所說的常量包括:基本類型包裝類(包裝類不管理浮點型,整形只會管理-128到127)和String(也可以通過String.intern()方法可以強制將String放入常量池)
;Compiled from "hello.java" public class hello {public hello();Code:0: aload_01: invokespecial #1 // Method java/lang/Object."<init>": ()V4: returnpublic static void main(java.lang.String[]);Code:0: bipush 1012: istore_13: return };Compiled from "hello2.java" public class hello2 {public hello2();Code:0: aload_01: invokespecial #1 // Method java/lang/Object."<init>": ()V4: returnpublic static void main(java.lang.String[]);Code:0: ldc #2 // int -21474836472: istore_13: getstatic #3 // Field java/lang/System.out:Ljava/ io/PrintStream;6: iload_17: invokevirtual #4 // Method java/io/PrintStream.printl n:(I)V10: ldc #5 // int -3276912: istore_213: getstatic #3 // Field java/lang/System.out:Ljava/ io/PrintStream;16: iload_217: invokevirtual #4 // Method java/io/PrintStream.printl n:(I)V20: ldc #6 // int 3276822: istore_323: ldc #7 // int 6553525: istore 427: ldc #8 // int 6553629: istore 531: ldc #9 // int 214748364733: istore 635: getstatic #3 // Field java/lang/System.out:Ljava/ io/PrintStream;38: iload 640: invokevirtual #4 // Method java/io/PrintStream.printl n:(I)V43: return }?
總結
以上是生活随笔為你收集整理的java虚拟机指令初步学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PowerDesigner中Stereo
- 下一篇: java虚拟机xadd指令学习