• JVM 字节码(三)异常在字节码中的处理(catch 和 throws)


    JVM 字节码(三)异常在字节码中的处理(catch 和 throws)

    在 ClassFile 中到底是如何处理异常的呢?

    一、代码块异常 catch

    catch 中的异常代码块在异常是如何处理的呢?还记得在 Code 属性中有如下的结构吗?这代码的是一个异常表信息。

    Code_attribute {
        ...
        u2 exception_table_length;
        {   u2 start_pc;
            u2 end_pc;
            u2 handler_pc;
            u2 catch_type;
        } exception_table[exception_table_length];
        ...
    }
    

    案例分析:

    public void test() {
        try {
            FileInputStream in = new FileInputStream("text.txt");
            ServerSocket serverSocket = new ServerSocket(9999);
            serverSocket.accept();
        } catch (FileNotFoundException e) {
        } catch (IOException e) {
        } catch (Exception e) {
        } finally {
            System.out.println("finally!");
        }
    }
    

    这段代码编译后用 jclasslib 查看,字节码和异常表分别如下:

     0 new #2 <java/io/FileInputStream>
     3 dup
     4 ldc #3 <text.txt>
     6 invokespecial #4 <java/io/FileInputStream.<init>>
     9 astore_1
    10 new #5 <java/net/ServerSocket>
    13 dup
    14 sipush 9999
    17 invokespecial #6 <java/net/ServerSocket.<init>>
    20 astore_2
    21 aload_2
    22 invokevirtual #7 <java/net/ServerSocket.accept>
    25 pop
    26 getstatic #8 <java/lang/System.out>
    29 ldc #9 <finally!>
    31 invokevirtual #10 <java/io/PrintStream.println>
    34 goto 84 (+50)
    37 astore_1
    38 getstatic #8 <java/lang/System.out>
    41 ldc #9 <finally!>
    43 invokevirtual #10 <java/io/PrintStream.println>
    46 goto 84 (+38)
    49 astore_1
    50 getstatic #8 <java/lang/System.out>
    53 ldc #9 <finally!>
    55 invokevirtual #10 <java/io/PrintStream.println>
    58 goto 84 (+26)
    61 astore_1
    62 getstatic #8 <java/lang/System.out>
    65 ldc #9 <finally!>
    67 invokevirtual #10 <java/io/PrintStream.println>
    70 goto 84 (+14)
    73 astore_3
    74 getstatic #8 <java/lang/System.out>
    77 ldc #9 <finally!>
    79 invokevirtual #10 <java/io/PrintStream.println>
    82 aload_3
    83 athrow
    84 return
    

    异常表如下:

    异常表

    解读一下异常表, start_pc ~ end_pc 出现的 catch_type 异常由 handler_pc 行的代码进行处理。

    • 第一行表示 0~26 行出现的 FileNotFoundException 异常直接跳转到 37(astore_1) 行
    • 第二行表示 0~26 行出现的 IOException 异常直接跳转到 49(astore_1) 行
    • 第三行表示 0~26 行出现的 Exception 异常直接跳转到 61(astore_1) 行
    • any 表示其余的所有异常,字节码层面定义,和 Java 中定义的 Exception 还不太一样

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

    1. 统一采用异常表的方式对异常进行处理。
    2. 在 JDK 1.4.2 之前的版本中,采用特定的指令方式。
    3. 当异常处理存在 finally 语句块时,JVM 采取的处理方式是将 finally 语句块的字节码拼接到每一个 catch 块后面

    二、方法级异常 throws

    public void test() throws FileNotFoundException, RuntimeException {
    }
    

    在上述方法上加上 FileNotFoundException, RuntimeException 两个异常重新编译后的字节码,方法多了一个 Exceptions 属性,这个属性和 Code 属性平级。

    Exceptions 属性

    参考:

    1. 周志明,深入理解Java虚拟机 - 第 6 章:类文件结构
    2. Java 反编译工具 - jclasslib(比 javap -v 信息更详细,可以在 IDEA 插件中直接下载)

    每天用心记录一点点。内容也许不重要,但习惯很重要!

  • 相关阅读:
    三维重建5:场景中语义分析/语义SLAM/DCNN-大尺度SLAM
    三维重建面试4:Jacobian矩阵和Hessian矩阵
    三维重建面试3:旋转矩阵-病态矩阵、欧拉角-万向锁、四元数
    人工机器:NDC-谷歌机器翻译破世界纪录,仅用Attention模型,无需CNN和RNN
    Cell期刊论文:为什么计算机人脸识别注定超越人类?(祖母论与还原论之争)
    三维重建面试2: 地图构建-三角测量
    三维重建面试1-位姿追踪:单应矩阵、本质矩阵和基本矩阵
    Caffe2:ubuntuKylin17.04使用Caffe2.LSTM
    三维重建面试0:*SLAM滤波方法的串联综述
    cannot find Toolkit in /usr/local/cuda-8.0
  • 原文地址:https://www.cnblogs.com/binarylei/p/10519660.html
Copyright © 2020-2023  润新知