zoukankan      html  css  js  c++  java
  • 通过字节码分析this关键字以及异常表的重要作用

    在之前的字节码分析中缺少对异常的介绍,这次主要来对字节码异常表相关的东东进行一个学习,下面先来编写一个相关异常的小程序:

    接着编译来看用javap -verbose来查看一下它的字节码信息:

    xiongweideMacBook-Pro:classes xiongwei$ javap -verbose com/jvm/bytecode/MyTest3.class 
    Classfile /Users/xiongwei/Documents/workspace/IntelliJSpace/jvm_lectue/out/production/classes/com/jvm/bytecode/MyTest3.class
      Last modified Sep 26, 2018; size 1056 bytes
      MD5 checksum 67ac394f07ca1303eb0119b94486d428
      Compiled from "MyTest3.java"
    public class com.jvm.bytecode.MyTest3
      minor version: 0
      major version: 52
      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/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/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/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.jvm.bytecode.MyTest3();
        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 9: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       5     0  this   Lcom/jvm/bytecode/MyTest3;
    
      public void test();
        descriptor: ()V
        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 14: 10
            line 15: 21
            line 23: 26
            line 24: 34
            line 16: 37
            line 23: 38
            line 24: 46
            line 18: 49
            line 23: 50
            line 24: 58
            line 20: 61
            line 23: 62
            line 24: 70
            line 23: 73
            line 24: 82
            line 25: 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/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 */
    }
    SourceFile: "MyTest3.java"

    其中重点观注一下test()方法的信息:

    其中stack表示这个方法运行的任何时刻所能达到的操作数栈的最大深度;local表示方法执行期间创建的局部变量的数目,包含用来表示传入的参数的局部变量。args_size表示方法的参数的总个数。
    下面首先来解释一下为啥args_size等于1,很明显咱们这个方法是一个无参的定义,关于这个在之前的学习中已经解释过了,这里再巩固一下:对于Java类中的每一个实例方法(非static方法),其在编译后所生成的字节码当中,方法参数的数量总是会比源代码中方法的参数的数量多一个(this),它位于方法的第一个参数位置处;这样,我们就可以在Java的实例方法中使用this来去访问当前对象的属性以及其它方法。这个操作是在编译期间完成的,既由javac编译器在编译的时候将对this的访问转化为对一个普通实例方法参数的访问,接下来的运行期间,由JVM在调用实例方法时,自动向实例方法传入该this参数。所以,在实例方法的局部变量表中,至少会有一个指向当前对象的局部变量【也就是会存在于下面要分析的locals中】

    接着来看一下locals,为啥有4个局部变量呢?下面来分析一下:
    1、当然就是隐含的this啦,上面分析stack中标明处有说明。

    2、当然就是is喽,如下:

    3、当然就是serverSocket喽:

    4、那它倒底是啥呢?貌似咱们能见到局部变量就木有了,其实这个局部变量是位于catch当中的,如下:

    也就是如果抛出了异常,那么最终这三个异常就会产生一个局部变量,如果不抛出异常,那么这个最多4个局部变量中最终只会使用3个局部变量。

    最后再来看一下statck=3,也就是这个方法最多能往栈中压入3个元素,关于栈在之后还会详述的,这里有个基本印象。

    接着来则到了该篇要讨论的核心话题:异常,对应方法的code属性中exception_table,这里存放的是处理异常的信息。每一个exception_table表项由start_pc、end_pc、handler_pc、catch_type组成,那这四个元素分别代表啥呢?下面来看一下:

    • start_pc和end_pc表示在code数组中的从start_pc到end_pc处(包含start_pc,不包含end_pc)的指令抛出的异常会由这个表项来处理。
    • handler_pc表示处理异常的代码的开始处。catch_type表示会被处理的异常类型,它指向常量池里的一个异常表。当catch_type为0时,表示处理所有的异常。

    其实异常在字节码中是存在有goto语句的,也就是当发生异常则会goto到指定的位置进行异常处理,大至看一下:

    具体异常相关的分析下次再继续。

  • 相关阅读:
    PS后期合成,你和大神的差距就这5步!
    欧几里得算法:从证明等式gcd(m, n) = gcd(n, m mod n)对每一对正整数m, n都成立说开去
    谜题:过桥问题
    《世界是数字的》读书笔记第一部分_硬件篇
    完全偶图K(3,3)与完全图K5是否存在平面表示
    Dijkstar算法的数学原理
    LeetCode 141. Linked List Cycle
    LeetCode 155. Min Stack
    LeetCode 160. Intersection of Two Linked Lists
    LeetCode 165.Compare Version Numbers
  • 原文地址:https://www.cnblogs.com/webor2006/p/9691523.html
Copyright © 2011-2022 走看看