天天看點

JVM系列_JVM操作指令集解析

1. 先寫一個簡單的程式并且運作:

package com.lic.hashMap;
public class Math {

	public int compute() {
		int a = 8;
		int b = 9;
		int c = (a + b) * 10;
		return c;
	}
	
	public static void main(String[] args) {
		Math math = new Math();
		math.compute();
	}
}
           

2.找到項目目錄下該Java檔案經過編譯後的class檔案:

JVM系列_JVM操作指令集解析

3.由于class檔案中是比較底層的機器語言, 是以需要對class檔案進行下次編譯, 使得具有一定可讀性; 所在在cmd視窗中切換到class所在目錄下, 執行javap指令

JVM系列_JVM操作指令集解析

注意: javap -v Math.class 會編譯出具有更多附加資訊的JVM指令

4.1 math.txt 來自javap Math.class 指令編譯後

Compiled from "Math.java"
public class com.lic.hashMap.Math {
  public com.lic.hashMap.Math();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public int compute();
    Code:
       0: bipush        8           //将一個8位帶符号整數8壓入棧     (将int類型常量8放入操作數棧中)
       2: istore_1					//将int類型的值8存入局部變量1中  (将局部變量a放入局部變量表,然後将int類型常量8從操作數棧中取出,存入局部變量a中)
       3: bipush        9			//将一個8位帶符号整數9壓入棧     (将int類型常量9放入操作數棧中)
       5: istore_2					//将int類型的值9存入局部變量2中  (将局部變量b放入局部變量表,然後将int類型常量9從操作數棧中取出,存入局部變量b中)
       6: iload_1   				//從局部變量1中裝載int類型值     (将局部變量1中的值壓入操作數棧)
       7: iload_2					//從局部變量2中裝載int類型值     (将局部變量2中的值壓入操作數棧)
       8: iadd						//執行int類型的加法		         (從操作數棧棧頂彈出兩個操作數,執行int類型的加法操作,執行結果存入操作數棧中)
       9: bipush        10			//将一個8位帶符号整數壓入棧		 (将int類型常量10放入操作數棧中)
      11: imul						//執行int類型的乘法				 (從操作數棧棧頂彈出兩個操作數,執行int類型的乘法操作,執行結果存入操作數棧中)		
      12: istore_3					//将int類型值存入局部變量3		 (将局部變量c放入局部變量表,然後将int類型常量從操作數棧中取出,存入局部變量c中)
      13: iload_3					//從局部變量3中裝載int類型值     (将局部變量3中的值壓入操作數棧)
      14: ireturn					//從方法中傳回int類型的資料      (将操作數棧棧頂元素彈出,傳回)

  public static void main(java.lang.String[]);
    Code:
       0: new           #1         //new -->建立一個新對象     //#1 --> class com/lic/hashMap/Math   
       3: dup					   //複制棧頂部一個字長内容
       4: invokespecial #22        //invokespecial -->根據編譯時類型來調用執行個體方法(執行初始化方法)  //#22 --> Method "<init>":()V		
       7: astore_1				   //将引用類型或returnAddress類型值存入局部變量1 (将建立的Math對象的位址存入局部變量math中)
       8: aload_1				   //從局部變量1中裝載引用類型值   (将局部變量math的值壓入操作數棧)
       9: invokevirtual #23        //invokespecial -->根據編譯時類型來調用執行個體方法(執行初始化方法)  //#23 --> Method compute:()I
      12: pop					   //彈出棧頂端一個字長的内容
      13: return				   //從方法中傳回,傳回值為void 
}

           

4.2 math1.txt 來自javap -v Math.class 指令編譯後

Classfile /D:/java/workspace/JDK1.8_Test/bin/com/lic/hashMap/math.class
  Last modified 2019-7-22; size 585 bytes
  MD5 checksum 6007ebac480a03b8b11f0b6fccdcafd3
  Compiled from "Math.java"
public class com.lic.hashMap.Math
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Class              #2             // com/lic/hashMap/Math
   #2 = Utf8               com/lic/hashMap/Math
   #3 = Class              #4             // java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Methodref          #3.#9          // java/lang/Object."<init>":()V
   #9 = NameAndType        #5:#6          // "<init>":()V
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/lic/hashMap/Math;
  #14 = Utf8               compute
  #15 = Utf8               ()I
  #16 = Utf8               a
  #17 = Utf8               I
  #18 = Utf8               b
  #19 = Utf8               c
  #20 = Utf8               main
  #21 = Utf8               ([Ljava/lang/String;)V
  #22 = Methodref          #1.#9          // com/lic/hashMap/Math."<init>":()V
  #23 = Methodref          #1.#24         // com/lic/hashMap/Math.compute:()I
  #24 = NameAndType        #14:#15        // compute:()I
  #25 = Utf8               args
  #26 = Utf8               [Ljava/lang/String;
  #27 = Utf8               math
  #28 = Utf8               SourceFile
  #29 = Utf8               Math.java
{
  public com.lic.hashMap.Math();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #8                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/lic/hashMap/Math;

  public int compute();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=1
       0: bipush        8           //将一個8位帶符号整數8壓入棧     (将int類型常量8放入操作數棧中)
       2: istore_1					//将int類型的值8存入局部變量1中  (将局部變量a放入局部變量表,然後将int類型常量8從操作數棧中取出,存入局部變量a中)
       3: bipush        9			//将一個8位帶符号整數9壓入棧     (将int類型常量9放入操作數棧中)
       5: istore_2					//将int類型的值9存入局部變量2中  (将局部變量b放入局部變量表,然後将int類型常量9從操作數棧中取出,存入局部變量b中)
       6: iload_1   				//從局部變量1中裝載int類型值     (将局部變量1中的值壓入操作數棧)
       7: iload_2					//從局部變量2中裝載int類型值     (将局部變量2中的值壓入操作數棧)
       8: iadd						//執行int類型的加法		         (從操作數棧棧頂彈出兩個操作數,執行int類型的加法操作,執行結果存入操作數棧中)
       9: bipush        10			//将一個8位帶符号整數壓入棧		 (将int類型常量10放入操作數棧中)
      11: imul						//執行int類型的乘法				 (從操作數棧棧頂彈出兩個操作數,執行int類型的乘法操作,執行結果存入操作數棧中)		
      12: istore_3					//将int類型值存入局部變量3		 (将局部變量c放入局部變量表,然後将int類型常量從操作數棧中取出,存入局部變量c中)
      13: iload_3					//從局部變量3中裝載int類型值     (将局部變量3中的值壓入操作數棧)
      14: ireturn					//從方法中傳回int類型的資料      (将操作數棧棧頂元素彈出,傳回)

      LineNumberTable:
        line 6: 0
        line 7: 3
        line 8: 6
        line 9: 13
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      15     0  this   Lcom/lic/hashMap/Math;
            3      12     1     a   I
            6       9     2     b   I
           13       2     3     c   I

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1				//注意: #1在上方的常量池中可以查找到相對的解釋
       0: new           #1         //new -->建立一個新對象     //#1 --> class com/lic/hashMap/Math   
       3: dup					   //複制棧頂部一個字長内容
       4: invokespecial #22        //invokespecial -->根據編譯時類型來調用執行個體方法(執行初始化方法)  //#22 --> Method "<init>":()V		
       7: astore_1				   //将引用類型或returnAddress類型值存入局部變量1 (将建立的Math對象的位址存入局部變量math中)
       8: aload_1				   //從局部變量1中裝載引用類型值   (将局部變量math的值壓入操作數棧)
       9: invokevirtual #23        //invokespecial -->根據編譯時類型來調用執行個體方法(執行初始化方法)  //#23 --> Method compute:()I
      12: pop					   //彈出棧頂端一個字長的内容
      13: return				   //從方法中傳回,傳回值為void 
      LineNumberTable:
        line 13: 0
        line 14: 8
        line 15: 13
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      14     0  args   [Ljava/lang/String;
            8       6     1  math   Lcom/lic/hashMap/Math;
}
SourceFile: "Math.java"

           

相關圖解:

JVM系列_JVM操作指令集解析