当前位置: 首页 > news >正文

【Java从入门到放弃 之 从字节码的角度异常处理】

从字节码的角度异常处理

  • 生成字节码
  • Javap 命令的使用
    • 基本语法
  • 字节码文件
    • testTryCatch
    • testTryCatchFinally
    • testTryWithResource

如果大家对与java的异常使用还有问题或者还不太了解,建议先看一下我之前写的Java异常了解一下基本 的异常处理知识,再看这篇文章。

生成字节码

public class Test27 {public String testTryCatch() {try {int a = 1;int b = 0;return String.valueOf(a / b);} catch (ArithmeticException e) {return "divide 0 ";}}public String testTryCatchFinally() {try {int a = 1;int b = 0;return String.valueOf(a / b);} catch (ArithmeticException e) {return "divide 0 ";}finally {System.out.println("finally");}}public String testTryWithResource() {try {int a = 1;int b = 0;return String.valueOf(a / b);} catch (ArithmeticException e) {return "divide 0 ";}finally {System.out.println("finally");}}}

执行javac命令编译成字节码文件

D:\project\mydemo\src\main\java\com\example\mydemo\test>javac Test27.java

Javap 命令的使用

javap 是 Java 提供的反汇编工具,用于将 Java 字节码文件(.class 文件)反汇编成人类可读的 Java 汇编代码(或者说是 Java 字节码的指令)。这对于理解 Java 编译器生成的字节码、学习 JVM 的工作原理、调试和优化代码都非常有用。

基本语法

javap [options] <classes>
D:\project\mydemo\src\main\java\com\example\mydemo\test>javap -c Test27.class

常用选项

  • -c:显示字节码指令(反汇编)。
  • -verbose:显示详细信息,包括类、字段、方法的签名和属性。
  • -l:显示行号和本地变量表信息。
  • -p:显示所有私有成员、受保护成员和默认(包)访问级别的成员。
  • -constants:显示静态常量池。
  • -classpath 或 -cp :指定类路径。
  • -s:显示内部类型签名。
  • -public:仅显示公共成员和类。
  • -protected:显示公共和受保护成员和类(默认行为)。
  • -package:显示公共和包访问级别的成员和类(不加 -p 时默认行为)。
  • -private:显示所有成员和类(包括私有成员)。

字节码文件

生成的完整的字节码文件我传上来了,有需要的可以下载,这里我们逐个分析每个方法的字节码。

testTryCatch

  public java.lang.String testTryCatch();Code:0: iconst_11: istore_12: iconst_03: istore_24: iload_15: iload_26: idiv7: invokestatic  #7                  // Method java/lang/String.valueOf:(I)Ljava/lang/String;10: areturn11: astore_112: ldc           #15                 // String divide 014: areturnException table:from    to  target type0    10    11   Class java/lang/ArithmeticException

0到3行,是把1跟0这两个常量存到slot里面;4到6是把两个操作数入栈,然后做除法。然后下面是异常表,如果from0 to 10 发生异常,跳转到target11行处理。

testTryCatchFinally

  public java.lang.String testTryCatchFinally();Code:0: iconst_11: istore_12: iconst_03: istore_24: iload_15: iload_26: idiv7: invokestatic  #7                  // Method java/lang/String.valueOf:(I)Ljava/lang/String;10: astore_311: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;14: ldc           #23                 // String finally16: invokevirtual #25                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V19: aload_320: areturn21: astore_122: ldc           #15                 // String divide 024: astore_225: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;28: ldc           #23                 // String finally30: invokevirtual #25                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V33: aload_234: areturn35: astore        437: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;40: ldc           #23                 // String finally42: invokevirtual #25                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V45: aload         447: athrowException table:from    to  target type0    11    21   Class java/lang/ArithmeticException0    11    35   any21    25    35   any35    37    35   any

这段字节码,我们主要观察Exception table,很明显

  1. 0 - 11 行如果发生Class java/lang/ArithmeticException则跳转到21行开始执行。
  2. 0 - 11行没有发生异常,则跳转到35行开始执行,实际上你仔细看的话,会发现,35行之后是finally的那部分。
  3. 21 - 25行执行的是catch块里面的语句,执行完之后也会自动跳转到35行执行
  4. 35 - 37行执行的是把异常class保存起来,以便执行throw的时候能正常抛出去。

testTryWithResource

  public java.lang.String testTryWithResource();Code:0: new           #31                 // class java/io/FileInputStream3: dup4: ldc           #33                 // String teset6: invokespecial #35                 // Method java/io/FileInputStream."<init>":(Ljava/lang/String;)V9: astore_110: ldc           #37                 // String ok12: astore_213: aload_114: invokevirtual #39                 // Method java/io/FileInputStream.close:()V17: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;20: ldc           #23                 // String finally22: invokevirtual #25                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V25: aload_226: areturn27: astore_228: aload_129: invokevirtual #39                 // Method java/io/FileInputStream.close:()V32: goto          4135: astore_336: aload_237: aload_338: invokevirtual #44                 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V41: aload_242: athrow43: astore_144: aload_145: invokevirtual #50                 // Method java/io/IOException.printStackTrace:()V48: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;51: ldc           #23                 // String finally53: invokevirtual #25                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V56: goto          7259: astore        461: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;64: ldc           #23                 // String finally66: invokevirtual #25                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V69: aload         471: athrow72: ldc           #37                 // String ok74: areturnException table:from    to  target type10    13    27   Class java/lang/Throwable28    32    35   Class java/lang/Throwable0    17    43   Class java/io/IOException27    43    43   Class java/io/IOException0    17    59   any27    48    59   any59    61    59   any

最后这段字节码我就不带大家一起读了,实际上你自己看就会发现,实际上TryWithResource是语法糖,把之前我们写的一些cath的内容,编译器帮我们添加进去了。编译器自动关闭资源的同时,也帮助我们把异常处理加了进去。如果有疑问的,欢迎评论,私信我。我有时间都会给大家回复解答的。

http://www.lryc.cn/news/497222.html

相关文章:

  • Java虚拟机(JVM)中的元空间(Metaspace)一些关键点的总结
  • 小程序 模版与配置
  • 当大的div中有六个小的div,上面三个下面三个,当外层div高变大的时候我希望里面的小的div的高也变大
  • MySQL——操作
  • Python语法之正则表达式详解以及re模块中的常用函数
  • 《地球化学》
  • alpine openssl 编译
  • 【AI模型对比】AI新宠Kimi与ChatGPT的全面对比:技术、性能、应用全揭秘
  • 【C#设计模式(17)——迭代器模式(Iterator Pattern)】
  • 二、部署docker
  • FFmpeg 4.3 音视频-多路H265监控录放C++开发十九,ffmpeg封装
  • ML 系列:第 39 节 - 估计方法:最大似然估计 (MLE)
  • Linux 权限管理:用户分类、权限解读与常见问题剖析
  • 网络原理之 UDP 协议
  • 并发框架disruptor实现生产-消费者模式
  • 【Vivado】xdc约束文件编写
  • Redis使用场景-缓存-缓存雪崩
  • 概率论相关知识随记
  • 【PlantUML系列】序列图(二)
  • WPF+MVVM案例实战与特效(三十四)- 日志管理:使用 log4net 实现高效日志记录
  • 前端测试框架 jasmine 的使用
  • Qwen2-VL视觉大模型微调实战:LaTex公式OCR识别任务(完整代码)
  • 「Mac玩转仓颉内测版42」小学奥数篇5 - 圆和矩形的面积计算
  • Groom Blender to UE5
  • 开发一套ERP 第十弹 图片作为配置文件,本地读取图片,定时更新图片类型
  • 第七十六条:努力保持故障的原子性
  • Word分栏后出现空白页解决方法
  • 基于HTML和CSS的校园网页设计与实现
  • 【算法day7】字符串:反转与替换
  • 分布式存储厂商