JVM探索字节码底层i++和++i的区别

1.查看代码的字节码文件

这是一个java文件
在这里插入图片描述
编译java文件
在这里插入图片描述
就会生成一个class文件
在这里插入图片描述
使用命令javap -v 获取字节码文件重定向到Test1.txt这个文件中
在这里插入图片描述
在这里插入图片描述
打开这个txt文件

Classfile /C:/Users/Administrator/Desktop/Test1.class
  Last modified 2019-4-17; size 572 bytes
  MD5 checksum ddb31aefaec5e019f1f6e133b22ea966
  Compiled from "Test1.java"
public class Test1
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #8.#19         // java/lang/Object."<init>":()V
   #2 = Class              #20            // Test1
   #3 = Methodref          #2.#19         // Test1."<init>":()V
   #4 = Methodref          #2.#21         // Test1.method1:()V
   #5 = Methodref          #2.#22         // Test1.method2:()V
   #6 = Fieldref           #23.#24        // java/lang/System.out:Ljava/io/PrintStream;
   #7 = Methodref          #25.#26        // java/io/PrintStream.println:(I)V
   #8 = Class              #27            // java/lang/Object
   #9 = Utf8               <init>
  #10 = Utf8               ()V
  #11 = Utf8               Code
  #12 = Utf8               LineNumberTable
  #13 = Utf8               main
  #14 = Utf8               ([Ljava/lang/String;)V
  #15 = Utf8               method1
  #16 = Utf8               method2
  #17 = Utf8               SourceFile
  #18 = Utf8               Test1.java
  #19 = NameAndType        #9:#10         // "<init>":()V
  #20 = Utf8               Test1
  #21 = NameAndType        #15:#10        // method1:()V
  #22 = NameAndType        #16:#10        // method2:()V
  #23 = Class              #28            // java/lang/System
  #24 = NameAndType        #29:#30        // out:Ljava/io/PrintStream;
  #25 = Class              #31            // java/io/PrintStream
  #26 = NameAndType        #32:#33        // println:(I)V
  #27 = Utf8               java/lang/Object
  #28 = Utf8               java/lang/System
  #29 = Utf8               out
  #30 = Utf8               Ljava/io/PrintStream;
  #31 = Utf8               java/io/PrintStream
  #32 = Utf8               println
  #33 = Utf8               (I)V
{
  public Test1();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V          //方法描述,V表示该方法的放回值为void
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1        
         0: new           #2                  // class Test1         
         3: dup
         4: invokespecial #3                  // Method "<init>":()V  
         7: invokevirtual #4                  // Method method1:()V
        10: new           #2                  // class Test1
        13: dup
        14: invokespecial #3                  // Method "<init>":()V
        17: invokevirtual #5                  // Method method2:()V
        20: return
      LineNumberTable:
        line 3: 0
        line 4: 10
        line 6: 20

  public void method1();
    descriptor: ()V                                     
    flags: ACC_PUBLIC
    Code:       
      stack=2, locals=3, args_size=1          // stack=2,操作栈的大小为2、locals=3,本地变量表大小,args_size=1, 参数
的个数
         0: iconst_1                        //将数字1压入到操作栈
         1: istore_1						  //将数字1从操作栈弹出,压入到本地变量表中,下标为1
         2: iload_1						  //从本地变量表中获取下标为1的数据,压入到操作栈中
         3: iinc          1, 1				  // 将本地变量中的1,再+1
         6: istore_2							// 将数字1从操作栈弹出,压入到本地变量表中,下标为2
         7: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
        10: iload_2							//从本地变量表中获取下标为2的数据,压入到操作栈中
        11: invokevirtual #7                  // Method java/io/PrintStream.println:(I)V
        14: return                            //结束
      LineNumberTable:
        line 8: 0                           
        line 9: 2
        line 10: 7
        line 11: 14
  public void method2();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: iconst_1							//将数字1压入到操作栈
         1: istore_1							//将数字1从操作栈弹出,压入到本地变量表中,下标为1
         2: iinc          1, 1					// 将本地变量中的1,再+1
         5: iload_1							//从本地变量表中获取下标为1的数据(2),压入到操作栈中
         6: istore_2							//将数字2从操作栈弹出,压入到本地变量表中,下标为2
         7: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
        10: iload_2							//从本地变量表中获取下标为2的数据(2),压入到操作栈中
        11: invokevirtual #7                  // Method java/io/PrintStream.println:(I)V
        14: return								 //结束
      LineNumberTable:
        line 13: 0
        line 14: 2
        line 15: 7
        line 16: 14
}
SourceFile: "Test1.java"

内容大致分为4个部分:
第一部分:显示了生成这个class的java源文件、版本信息、生成时间等。
第二部分:显示了该类中所涉及到常量池,共35个常量。
第三部分:显示该类的构造器,编译器自动插入的。
第四部分:显示了main方的信息。(这个是需要我们重点关注的)

常量池
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4-140

2.查看具体代码逻辑

在这里插入图片描述
具体什么意思我在上面都有文字说明

3.画图解释

文字有可能说不明白,下面画图解释

i++
在这里插入图片描述
在这里插入图片描述
++i我就不再做了,可以自己尝试一下
在这里插入图片描述
纯手写点个赞!

猜你喜欢

转载自blog.csdn.net/VinceZxy/article/details/89353774