• 【JVM学习笔记】异常表的重要作用以及locals属性的含义


    有如下代码

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

    javap -verbose -p Test 结果如下

    D:workspace-learncommon-learnlearn-classloader	argetclassescomlearnjvm>javap -verbose -p Test
    警告: 二进制文件Test包含com.learn.jvm.Test
    Classfile /D:/workspace-learn/common-learn/learn-classloader/target/classes/com/learn/jvm/Test.class
      Last modified 2019-9-5; size 1075 bytes
      MD5 checksum 744e2b9632f4d7f2d38d6b77b4225cc2
      Compiled from "Test.java"
    public class com.learn.jvm.Test
      SourceFile: "Test.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 block
      #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/learn/jvm/Test
      #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/learn/jvm/Test;
      #23 = Utf8               work
      #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               Test.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 block
      #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/learn/jvm/Test
      #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.learn.jvm.Test();
        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 14: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                   0       5     0  this   Lcom/learn/jvm/Test;
    
      public void work();
        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 block
            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 block
            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 block
            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 block
            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 block
            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
                37    38    73   any
                49    50    73   any
                61    62    73   any
                73    74    73   any
          LineNumberTable:
            line 17: 0
            line 18: 10
            line 19: 21
            line 27: 26
            line 28: 34
            line 20: 37
            line 27: 38
            line 28: 46
            line 22: 49
            line 27: 50
            line 28: 58
            line 24: 61
            line 27: 62
            line 28: 70
            line 27: 73
            line 29: 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/learn/jvm/Test;
          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 */
    
    }

    在上图中看到work方法的 stack=3, locals=4, args_size=1,其中size = 1表示参数个数为一个,即this,locals=4表示有4个局部变量,分别为 this,is,serverSocket,和 e,虽然有三个catch块,但是程序运行时只可能进入其中某一个,所以只有一个e

    对异常表的解读

     异常表的第一行为例,表示在[0,25]行这个范围内如果发生FileNotFoundException,将会跳转到字节码第37行,如下图

     astore_1表示把一个引用赋值给局部变量e


    Java字节码对于异常的处理方式:

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

    最后,如果方法后面throws了异常,则字节码里方法会多出一个属性,是这样的:

     很简单,知道即可

  • 相关阅读:
    算法导论第十三章:红黑树
    算法导论:相关数学问题小结
    STL_源码剖析之三:迭代器与traits
    算法导论第十二章:二叉查找树
    Common Lisp专家Peter Seibel对Google公司首席Java架构师Joshua Bloch的访谈(摘一段)
    STL源码剖析之六:算法
    STL 源码剖析之四:序列式容器
    算法导论第十四章:数据结构的扩张
    链表的归并排序:来自STL_ list_ sort 算法
    STL源码剖析之五:关联式容器
  • 原文地址:https://www.cnblogs.com/heben/p/11470675.html
Copyright © 2020-2023  润新知