在前面的文章中,有详细地介绍java字节码相关的知识,有兴趣的可以提前了解一下。
目录
从字节码角度来分析:异常处理
1.1 异常-catch
- // 从字节码角度来分析:异常处理
- public class T13_ByteAnalyseException {
- public static void main(String[] args) {
- int i = 0;
- try {
- i = 10;
- } catch (Exception e) {
- i = 20;
- }
- }
- }
注意:为了抓住重点,下面的字节码省略了不重要的部分
上述代码通过:javap -v T13_ByteAnalyseException.class进行反编译,得到如下字节码。
- public static void main(java.lang.String[]);
- descriptor: ([Ljava/lang/String;)V
- flags: ACC_PUBLIC, ACC_STATIC
- Code:
- stack=1, locals=3, args_size=1
- 0: iconst_0
- 1: istore_1
- 2: bipush 10
- 4: istore_1
- 5: goto 12
- 8: astore_2 // 将异常对象引用存入局部变量表的 slot 2号位置
- 9: bipush 20
- 11: istore_1
- 12: return
- Exception table: // 异常表,含头不含尾;一旦2~4行代码异常就进入异常判断是否是声明的Exception异常一致,如果一致就进入第8行
- from to target type
- 2 5 8 Class java/lang/Exception
- LineNumberTable:
- line 15: 0
- line 17: 2
- line 20: 5
- line 18: 8
- line 19: 9
- line 21: 12
- LocalVariableTable:
- Start Length Slot Name Signature
- 9 3 2 e Ljava/lang/Exception;
- 0 13 0 args [Ljava/lang/String;
- 2 11 1 i I
- StackMapTable: ...
上述说明:
- 可以看到多出来一个Exception table的结构,[from, to)是前闭后开的检测范围,一旦这个范围内的字节码执行出现异常,则通过type匹配异常类型,如果一致,进入target所指示行号
- 8行的字节码指令 astore_2 是将异常对象引用存入局部变量表的 slot 2号位置
1.2 异常-多个catch
先来看下异常-多个catch代码示例:
- // 从字节码角度来分析:多个 single-catch 块的情况
- public class T14_ByteAnalyseMoreSingle_Catch {
- public static void main(String[] args) {
- int i = 0;
- try {
- i = 10;
- } catch (ArithmeticException e) {
- i = 30;
- } catch (NullPointerException e) {
- i = 40;
- } catch (Exception e) {
- i = 50;
- }
- }
- }
上述代码通过:javap -v T14_ByteAnalyseMoreSingle_Catch.class进行反编译,得到如下字节码。
- public static void main(java.lang.String[]);
- descriptor: ([Ljava/lang/String;)V
- flags: ACC_PUBLIC, ACC_STATIC
- Code:
- stack=1, locals=3, args_size=1
- 0: iconst_0
- 1: istore_1
- 2: bipush 10
- 4: istore_1
- 5: goto 26
- 8: astore_2
- 9: bipush 30
- 11: istore_1
- 12: goto 26
- 15: astore_2
- 16: bipush 40
- 18: istore_1
- 19: goto 26
- 22: astore_2
- 23: bipush 50
- 25: istore_1
- 26: return
- Exception table:
- from to target type
- 2 5 8 Class java/lang/ArithmeticException
- 2 5 15 Class java/lang/NullPointerException
- 2 5 22 Class java/lang/Exception
- LineNumberTable: ...
- LocalVariableTable: // 因为异常最终只会出现一种,这里采用了异常引用变量的槽位复用
- Start Length Slot Name Signature
- 9 3 2 e Ljava/lang/ArithmeticException;
- 16 3 2 e Ljava/lang/NullPointerException;
- 23 3 2 e Ljava/lang/Exception;
- 0 27 0 args [Ljava/lang/String;
- 2 25 1 i I
- StackMapTable: ...
上述说明:
- 因为异常出现时,只能进入 Exception table 中一个分支,所以局部变量表 slot 2 位置被共用。也算是一种优化,为节省栈帧内存的使用
1.3 异常-multicatch
先来看下异常-multi_catch代码示例:
- // 从字节码角度来分析:multi-catch 的情况
- // jdk1.7 新增multi catch
- public class T15_ByteAnalyseMulti_Catch {
- public static void main(String[] args) {
- try {
- Method test = T15_ByteAnalyseMulti_Catch.class.getMethod("test");
- test.invoke(null);
- } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
- e.printStackTrace();
- }
- }
- public static void test() {
- System.out.println("ok");
- }
- }
上述代码通过:javap -v T15_ByteAnalyseMulti_Catch.class进行反编译,得到如下字节码。
- public static void main(java.lang.String[]);
- descriptor: ([Ljava/lang/String;)V
- flags: ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=2, args_size=1
- 0: ldc #2 // class com/jvm/t07_bytecode/T15_ByteAnalyseMulti_Catch
- 2: ldc #3 // String test
- 4: iconst_0
- 5: anewarray #4 // class java/lang/Class
- 8: invokevirtual #5 // Method java/lang/Class.getMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
- 11: astore_1
- 12: aload_1
- 13: aconst_null
- 14: iconst_0
- 15: anewarray #6 // class java/lang/Object
- 18: invokevirtual #7 // Method java/lang/reflect/Method.invoke:(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
- 21: pop
- 22: goto 30
- 25: astore_1
- 26: aload_1
- 27: invokevirtual #11 // e.printStackTrace:()V
- 30: return
- Exception table:
- from to target type
- 0 22 25 Class java/lang/NoSuchMethodException
- 0 22 25 Class java/lang/IllegalAccessException
- 0 22 25 Class java/lang/reflect/InvocationTargetException
- LineNumberTable: ...
- LocalVariableTable:
- Start Length Slot Name Signature
- 12 10 1 test Ljava/lang/reflect/Method;
- 26 4 1 e Ljava/lang/ReflectiveOperationException;
- 0 31 0 args [Ljava/lang/String;
上述说明:
- 异常-multi_catch 字节码 对比 异常-多个catch字节码,并没有特别的地方,只是异常表Exception table 三个异常的 target都一致。也有 异常-多个catch字节码 异常对象引用在局部变量表中槽位复用。
文章最后,给大家推荐一些受欢迎的技术博客链接:
- Hadoop相关技术博客链接
- Spark 核心技术链接
- JAVA相关的深度技术博客链接
- 超全干货--Flink思维导图,花了3周左右编写、校对
- 深入JAVA 的JVM核心原理解决线上各种故障【附案例】
- 请谈谈你对volatile的理解?--最近小李子与面试官的一场“硬核较量”
- 聊聊RPC通信,经常被问到的一道面试题。源码+笔记,包懂
欢迎扫描下方的二维码或 搜索 公众号“10点进修”,我们会有更多、且及时的资料推送给您,欢迎多多交流!
评论记录:
回复评论: