• 通过字节码分析this关键字以及异常表的作用


    1、创建MyTest3类

    public class MyTest3 {
    
        public void test(){
            try {
                InputStream is = new FileInputStream("test.txt");
    
                ServerSocket serverSocket = new ServerSocket(9999);
                serverSocket.accept();
            }catch (FileNotFoundException ex){
    
            }catch (IOException ex){
    
            } catch (Exception ex){
    
            }finally {
                System.out.println("finally");
            }
        }
    }
    

      然后生成字节码

    D:workspacestudy jvm_demouildclassesjavamaincomexamplejvmytecode>javap -verbose MyTest3.class

    Classfile /D:/workspace/study/ jvm_demo/build/classes/java/main/com/example/jvm/bytecode/MyTest3.class
      Last modified 2019-6-29; size 1068 bytes
      MD5 checksum a51a76cf80a500bc95a8d3d20f7d2a0e
      Compiled from "MyTest3.java"
    public class com.example.jvm.bytecode.MyTest3
      SourceFile: "MyTest3.java"
      minor version: 0
      major version: 51
      flags: ACC_PUBLIC, ACC_SUPER
    Constant pool:
       #1 = Methodref          #15.#35        //  java/lang/Object."<init>":()V
       #2 = Class              #36            //  java/io/FileInputStream
       #3 = String             #37            //  test.txt
       #4 = Methodref          #2.#38         //  java/io/FileInputStream."<init>":(Ljava/lang/String;)V
       #5 = Class              #39            //  java/net/ServerSocket
       #6 = Methodref          #5.#40         //  java/net/ServerSocket."<init>":(I)V
       #7 = Methodref          #5.#41         //  java/net/ServerSocket.accept:()Ljava/net/Socket;
       #8 = Fieldref           #42.#43        //  java/lang/System.out:Ljava/io/PrintStream;
       #9 = String             #44            //  finally
      #10 = Methodref          #45.#46        //  java/io/PrintStream.println:(Ljava/lang/String;)V
      #11 = Class              #47            //  java/io/FileNotFoundException
      #12 = Class              #48            //  java/io/IOException
      #13 = Class              #49            //  java/lang/Exception
      #14 = Class              #50            //  com/example/jvm/bytecode/MyTest3
      #15 = Class              #51            //  java/lang/Object
      #16 = Utf8               <init>
      #17 = Utf8               ()V
      #18 = Utf8               Code
      #19 = Utf8               LineNumberTable
      #20 = Utf8               LocalVariableTable
      #21 = Utf8               this
      #22 = Utf8               Lcom/example/jvm/bytecode/MyTest3;
      #23 = Utf8               test
      #24 = Utf8               is
      #25 = Utf8               Ljava/io/InputStream;
      #26 = Utf8               serverSocket
      #27 = Utf8               Ljava/net/ServerSocket;
      #28 = Utf8               StackMapTable
      #29 = Class              #47            //  java/io/FileNotFoundException
      #30 = Class              #48            //  java/io/IOException
      #31 = Class              #49            //  java/lang/Exception
      #32 = Class              #52            //  java/lang/Throwable
      #33 = Utf8               SourceFile
      #34 = Utf8               MyTest3.java
      #35 = NameAndType        #16:#17        //  "<init>":()V
      #36 = Utf8               java/io/FileInputStream
      #37 = Utf8               test.txt
      #38 = NameAndType        #16:#53        //  "<init>":(Ljava/lang/String;)V
      #39 = Utf8               java/net/ServerSocket
      #40 = NameAndType        #16:#54        //  "<init>":(I)V
      #41 = NameAndType        #55:#56        //  accept:()Ljava/net/Socket;
      #42 = Class              #57            //  java/lang/System
      #43 = NameAndType        #58:#59        //  out:Ljava/io/PrintStream;
      #44 = Utf8               finally
      #45 = Class              #60            //  java/io/PrintStream
      #46 = NameAndType        #61:#53        //  println:(Ljava/lang/String;)V
      #47 = Utf8               java/io/FileNotFoundException
      #48 = Utf8               java/io/IOException
      #49 = Utf8               java/lang/Exception
      #50 = Utf8               com/example/jvm/bytecode/MyTest3
      #51 = Utf8               java/lang/Object
      #52 = Utf8               java/lang/Throwable
      #53 = Utf8               (Ljava/lang/String;)V
      #54 = Utf8               (I)V
      #55 = Utf8               accept
      #56 = Utf8               ()Ljava/net/Socket;
      #57 = Utf8               java/lang/System
      #58 = Utf8               out
      #59 = Utf8               Ljava/io/PrintStream;
      #60 = Utf8               java/io/PrintStream
      #61 = Utf8               println
    {
      public com.example.jvm.bytecode.MyTest3();
        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 9: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                   0       5     0  this   Lcom/example/jvm/bytecode/MyTest3;
    
      public void test();
        flags: ACC_PUBLIC
        Code:
          stack=3, locals=4, args_size=1
             0: new           #2                  // class java/io/FileInputStream
             3: dup
             4: ldc           #3                  // String test.txt
             6: invokespecial #4                  // Method java/io/FileInputStream."<init>":(Ljava/lang/String;)V
             9: astore_1
            10: new           #5                  // class java/net/ServerSocket
            13: dup
            14: sipush        9999
            17: invokespecial #6                  // Method java/net/ServerSocket."<init>":(I)V
            20: astore_2
            21: aload_2
            22: invokevirtual #7                  // Method java/net/ServerSocket.accept:()Ljava/net/Socket;
            25: pop
            26: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
            29: ldc           #9                  // String finally
            31: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
            34: goto          84
            37: astore_1
            38: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
            41: ldc           #9                  // String finally
            43: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
            46: goto          84
            49: astore_1
            50: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
            53: ldc           #9                  // String finally
            55: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
            58: goto          84
            61: astore_1
            62: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
            65: ldc           #9                  // String finally
            67: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
            70: goto          84
            73: astore_3
            74: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
            77: ldc           #9                  // String finally
            79: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
            82: aload_3
            83: athrow
            84: return
          Exception table:
             from    to  target type
                 0    26    37   Class java/io/FileNotFoundException
                 0    26    49   Class java/io/IOException
                 0    26    61   Class java/lang/Exception
                 0    26    73   any
          LineNumberTable:
            line 13: 0
            line 15: 10
            line 16: 21
            line 24: 26
            line 25: 34
            line 17: 37
            line 24: 38
            line 25: 46
            line 19: 49
            line 24: 50
            line 25: 58
            line 21: 61
            line 24: 62
            line 25: 70
            line 24: 73
            line 26: 84
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                  10      16     1    is   Ljava/io/InputStream;
                  21       5     2 serverSocket   Ljava/net/ServerSocket;
                   0      85     0  this   Lcom/example/jvm/bytecode/MyTest3;
          StackMapTable: number_of_entries = 5
               frame_type = 101 /* same_locals_1_stack_item */
              stack = [ class java/io/FileNotFoundException ]
               frame_type = 75 /* same_locals_1_stack_item */
              stack = [ class java/io/IOException ]
               frame_type = 75 /* same_locals_1_stack_item */
              stack = [ class java/lang/Exception ]
               frame_type = 75 /* same_locals_1_stack_item */
              stack = [ class java/lang/Throwable ]
               frame_type = 10 /* same */
    
    }
    

      查看test方法

    stack=3:表示操作数栈的最大深度为3

    locals=4: 声明的局部变量的数目为4

    args_size=1:  方法本身接收到的参数的数量

    思考1:test方法没有接收参数,但是args_size=1表示接收参数为1 ?

           对于Java类中的每一实例方法(非static方法),其在编译后所生成的字节码当中,方法参数的数量总是会比源代码中方法参数的数量多一个(this),它位于方法的第一个参数位置处; 这样,我们就可以在Java的实例方法中使用this来去访问当前对象的属性以及其他方法。

       这个操作是在编译期间完成的,即由javac编译期在编译的时候将对this的访问转化为对一个普通实例方法参数的访问,接下来在运行期间,由JVM在调用实例方法时,自动向实例方法传入this参数。所以,在实例方法的局部表里表中,至少会有一个指向当前对象的局部变量。

    思考2: locals=4,声明的局部变量的数目为4,分别是哪4个?

    this,is, serverSocket,ex

    stack=3,操作数栈的最大深度

    2、异常表
    如下图的三个异常

    Java字节码对于异常的处理方式:
    1、统一采用异常表的方式来对异常进行处理
    2、在jdk1.4.2之前的的版本中,并不是对异常表的方式来对异常进行处理的,而是采用特定的指令方式
    3、当异常处理存在finally语句块时,现代化的JVM采取的处理方式是将finally语句块的字节码拼接到每一个catch块后面
    换句话说,程序中存在多少个catch块,就会在每一个catch块后面重复多少个finally语句的字节码


    然后在方法里抛出异常,

    反编译后查看



  • 相关阅读:
    内建函数
    urllib学习
    Jupyter Notebook介绍、安装及使用教程
    grep详解、sed详解、awk详解
    正则表达式
    RedisClient.SetRandomMember
    redis 队列
    hmGet
    redis trim
    大O符号
  • 原文地址:https://www.cnblogs.com/linlf03/p/11107144.html
Copyright © 2020-2023  润新知