zoukankan      html  css  js  c++  java
  • Java字节码例子解析

    举个简单的例子:

    public class Hello {
        public static void main(String[] args) {
            String string1 = "ab";
            String string2 = "c";
            String string3 = string1 + "c";
            System.out.println(string1 == string3);
        }
    }

    过程大致分析如图:

    第一步 将线程栈中的string1、string2引用分别指向了常量池ab、c的地址。

    第二步 轮到了string3 = string1 + "c",首先会初始化StringBuilder到堆中,然后调append将string1字符串拼接、然后调append再拼接"c"。

    第三步 StringBuilder指向常量池的"abc"地址,然后通过toString返回值.

    然后执行如下指令:

    $ javac Hello.java   //编译
     
    $ javap -verbose Hello   //反编译,结果如下:
    Classfile /C:/Users/lisam/Desktop/新建文件夹/Hello.class
     
      Last modified 2018-9-17; size 706 bytes
     
      MD5 checksum 4d2164bd48f0690cad84271e27b237a5
     
      Compiled from "Hello.java"
     
    public class Hello
     
      SourceFile: "Hello.java"
     
      minor version: 0
     
      major version: 51
     
      flags: ACC_PUBLIC, ACC_SUPER
     
    //方法常量池
     
    Constant pool:
     
       #1 = Methodref          #11.#24        //  java/lang/Object."<init>":()V
     
       #2 = String             #25            //  ab
     
       #3 = String             #26            //  c
     
       #4 = Class              #27            //  java/lang/StringBuilder
     
       #5 = Methodref          #4.#24         //  java/lang/StringBuilder."<init>":()V
     
       #6 = Methodref          #4.#28         //  java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     
       #7 = Methodref          #4.#29         //  java/lang/StringBuilder.toString:()Ljava/lang/String;
     
       #8 = Fieldref           #30.#31        //  java/lang/System.out:Ljava/io/PrintStream;
     
       #9 = Methodref          #32.#33        //  java/io/PrintStream.println:(Z)V
     
      #10 = Class              #34            //  Hello
     
      #11 = Class              #35            //  java/lang/Object
     
      #12 = Utf8               <init>
     
      #13 = Utf8               ()V
     
      #14 = Utf8               Code
     
      #15 = Utf8               LineNumberTable
     
      #16 = Utf8               main
     
      #17 = Utf8               ([Ljava/lang/String;)V
     
      #18 = Utf8               StackMapTable
     
      #19 = Class              #36            //  "[Ljava/lang/String;"
     
      #20 = Class              #37            //  java/lang/String
     
      #21 = Class              #38            //  java/io/PrintStream
     
      #22 = Utf8               SourceFile
     
      #23 = Utf8               Hello.java
     
      #24 = NameAndType        #12:#13        //  "<init>":()V
     
      #25 = Utf8               ab
     
      #26 = Utf8               c
     
      #27 = Utf8               java/lang/StringBuilder
     
      #28 = NameAndType        #39:#40        //  append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     
      #29 = NameAndType        #41:#42        //  toString:()Ljava/lang/String;
     
      #30 = Class              #43            //  java/lang/System
     
      #31 = NameAndType        #44:#45        //  out:Ljava/io/PrintStream;
     
      #32 = Class              #38            //  java/io/PrintStream
     
      #33 = NameAndType        #46:#47        //  println:(Z)V
     
      #34 = Utf8               Hello
     
      #35 = Utf8               java/lang/Object
     
      #36 = Utf8               [Ljava/lang/String;
     
      #37 = Utf8               java/lang/String
     
      #38 = Utf8               java/io/PrintStream
     
      #39 = Utf8               append
     
      #40 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
     
      #41 = Utf8               toString
     
      #42 = Utf8               ()Ljava/lang/String;
     
      #43 = Utf8               java/lang/System
     
      #44 = Utf8               out
     
      #45 = Utf8               Ljava/io/PrintStream;
     
      #46 = Utf8               println
     
      #47 = Utf8               (Z)V
     
    {
     
      public Hello();
     
        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[]);
     
        flags: ACC_PUBLIC, ACC_STATIC
     
     
     
        Code:
     
          stack=3, locals=4, args_size=1
     
             //将字符串"ab"压入常量池
     
             0: ldc           #2                  // String ab
     
             //存储到局部变量表
     
             2: astore_1      
     
             //将字符串"c"压入常量池
     
             3: ldc           #3                  // String c
     
             //存储到局部变量表
     
             5: astore_2      
     
             //String3的拼接过程中,会先new
     
             6: new           #4                  // class java/lang/StringBuilder
     
             9: dup           
     
             //然后invokespecial调用初始化StringBuilder构造器
     
            10: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
     
            //把局部变量表中n=1的引用(即步骤2: astore_1)的值"ab"装在到操作数栈中。
     
            13: aload_1       
     
            //然后invokevirtual来调用方法append  string1
     
            14: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     
            //将字符串"c"压入常量池
     
            17: ldc           #3                  // String c
     
            //然后append "c"
     
            19: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     
            //调用toString返回值
     
            22: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     
            //然后将string3的值"abc"存储到局部变量表
     
            25: astore_3      
     
            //获取类的静态域,这里拿到了静态System.out,并将值压入栈顶
     
            26: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
     
            //把局部变量表中n=1的引用(即步骤2: astore_1)的值"ab"装在到操作数栈中。
     
            29: aload_1      
     
            //把局部变量表中n=3的引用(即步骤25: astore_3)的值"abc"装在到操作数栈中。
     
            30: aload_3       
     
            //比较上面栈顶两引用型数值,当结果不相等时跳转
     
            31: if_acmpne     38
     
            //将int为1压入栈顶
     
            34: iconst_1      
     
            35: goto          39
     
            38: iconst_0      
     
            //调用静态类中System.out.println
     
            39: invokevirtual #9                  // Method java/io/PrintStream.println:(Z)V
     
            //返回空
     
            42: return        
     
          LineNumberTable:
     
            line 3: 0
     
            line 4: 3
     
            line 5: 6
     
            line 6: 26
     
            line 7: 42
     
          StackMapTable: number_of_entries = 2
     
               frame_type = 255 /* full_frame */
     
              offset_delta = 38
     
              locals = [ class "[Ljava/lang/String;", class java/lang/String, class java/lang/String, class java/lang/String ]
     
              stack = [ class java/io/PrintStream ]
     
               frame_type = 255 /* full_frame */
     
              offset_delta = 0
     
              locals = [ class "[Ljava/lang/String;", class java/lang/String, class java/lang/String, class java/lang/String ]
     
              stack = [ class java/io/PrintStream, int ]
     
     
     
    }
     

    原文链接:Java字节码例子解析 - Lisam Blog - CSDN博客  https://blog.csdn.net/qq_28666081/article/details/82749655

    参考链接:一文让你明白Java字节码 - 简书  https://www.jianshu.com/p/252f381a6bc4

  • 相关阅读:
    架构师如何才能够设计一个安全的架构
    Google Analytics实用用小技巧
    如何从Linux系统中删除用户账户
    使用C++编译器的编译流程
    JavaScript中双叹号的使用实例
    Android合并文件的三种方式代码
    自学Linux命令的四种方法
    前端工程师必备实用网站
    给 iOS App 开发者的 39 个开源的 Swift UI 库
    关于iOS项目的一本书
  • 原文地址:https://www.cnblogs.com/tongongV/p/11138194.html
Copyright © 2011-2022 走看看