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到指定的位置进行异常处理,大至看一下:

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

  • 相关阅读:
    将PHP文件生成静态文件源码
    Entity Framework Code First 学习日记(6)一对多关系
    Entity Framework Code First 学习日记(5)
    Entity Framework Code First 学习日记(3)
    Entity Framework Code First 学习日记(7)多对多关系
    Entity Framework Code First学习日记(2)
    Entity Framework Code First 学习日记(8)一对一关系
    Entity Framework Code First 学习日记(9)映射继承关系
    Entity Framework Code First 学习日记(10)兼容遗留数据库
    Entity Framework Code First 学习日记(4)
  • 原文地址:https://www.cnblogs.com/webor2006/p/9691523.html
Copyright © 2011-2022 走看看