JVM学习-字节码指令集(四)

异常处理指令
抛出异常指令
  • athrow指令:在Java程序中显示抛出异常的操作(throw语句)都是由athrow指令来实现
  • 除了throw语句显示抛出异常情况之外,JVM规范还规定了许多运行时异常会在其他Java虚拟机指令检测到异常状况时自动抛出,在之前介绍的整数运算时,当除数为零时,虚拟机会在idiv或ldiv指令中抛出ArithmeticException异常
  • 注:正常情况下,操作数栈的压入弹出是一条条指令完成,唯一的例外情况是在抛异常时,Java虚拟机会清除操作数栈上的所有内容,而后将异常实例压入调用者操作数栈上
异常处理与异常表
处理异常
  • Java虚拟机中,处理异常 (catch语句)不是由字节码指令来实现,而是采用异常表来完成的
异常表
  • 如果一个方法定义了一个try-catch或者try-finally的异常处理,就会创建一个异常表,它包含了每个异常处理或者finally块的信息,异常表保存了每个异常处理信息,如
  • 起始位置
  • 结束位置
  • 程序计数器记录的代码处理的偏移地址
  • 被捕获的异常类在常量池中的索引
  • 当一个异常被抛出时,JVM会在当前的方法寻找一个匹配的处理,如果没有找到,这个方法会强制结束并弹出当前栈顶,并且异常会重新抛给上层调用的方法。如果在所有栈帧弹出前仍然没有找到合适的异常处理,这个线程将终止,如果这个异常在最后一个非守护线程里抛出,将会导致JVM自己终止,比如这个线程是个main线程
  • 不管什么时候抛出异常,如果异常处理最终匹配了所有异常类型,代码就会继续执行,这种情况下,如果方法结束后没有抛出异常,仍然执行finally块,在return前,它直接跳到finally块来完成目标
同步控制指令--通过monitor支持
方法级同步
  • 方法级同步是隐式的,即无须通过字节码指令来控制,它实现在方法调用和返回操作中,虚拟机可以从方法常量池的方法表结构中的ACC_SYCHRONIZED访问标志得知一个方法是否声明为同步方法
  • 当调用方法时,调用指令将会检查方法的ACC_SYCHRONIZED访问标志是否设置
  • 如果设置了,执行线程将先持有同步锁,然后执行方法,最后在方法完成时释放同步锁
  • 在方法执行期间,执行线程有了同步锁,其他任何线程都无法再获得一个锁
  • 如果一个同步方法执行期间抛出了异常,并且在方法内部无法处理此异常,那这个同步方法所持有的锁都将在异常抛到同步方法外自动释放
java 复制代码
private int i = 0;
    public synchronized void add() {
        i++;
    }
//字节码
 0 aload_0
 1 dup
 2 getfield #2 <com/chapter10/SychronizedTest.i>
 5 iconst_1
 6 iadd
 7 putfield #2 <com/chapter10/SychronizedTest.i>
10 return
  • 注:这段代码和普通无同步操作代码没有不同,没有使用monitorenter和monitorexit进行同步区控制,因为对于同步方法而言,当虚拟机通过方法的访问标示符判断是一个同步方法时,会自动在方法调用前进行加锁,不同步方法执行完毕后,不管方法是正常结束还是有异常抛出,均由虚拟机释放这个锁,因此,对于同步方法而言,monitorenter和monitorexit指令是隐式存在的,并未直接出现在字节码中。
方法内部一段指令序列的同步
  • 同步一段指令集序列:通常是由java中的sychronized语句块来表示的,JVM的指令集有monitorenter和monitorexit两条指令来支持sychronized关键字的语义。
  • 当一个线程进入同步代码块时,它使用monitorenter指令请求进入,如果当前对象的监视器计数器为0,则它会被准许进入,若为1,则判断持有当前监视器的线程是否为自己,如果是,则进入,否则进行等待,直到对象的监视器计数器为0,才会被允许进入同步块
  • 当线程退出同步块时,需要使用monitorexit声明退出,在Java虚拟机中,任何对象都有一个监视器与之相关联,用来判断对象是否被锁定,当监视器被持有后,对象处于锁定状态
  • 指令monitorenter和monitorexit在执行时,需要在操作数栈顶压入对象,之后monitorenter和monitorexit的锁定和释放都是针对这个对象的监视器进行的
  • 监视器如何保护临界区代码不同时被多个线程访问,只有当线程4离开临界区时,线程1-3其中一个才能进入
相关推荐
侠客行03179 小时前
Mybatis连接池实现及池化模式
java·mybatis·源码阅读
蛇皮划水怪9 小时前
深入浅出LangChain4J
java·langchain·llm
老毛肚11 小时前
MyBatis体系结构与工作原理 上篇
java·mybatis
阿蒙Amon11 小时前
TypeScript学习-第10章:模块与命名空间
学习·ubuntu·typescript
AI绘画哇哒哒11 小时前
【干货收藏】深度解析AI Agent框架:设计原理+主流选型+项目实操,一站式学习指南
人工智能·学习·ai·程序员·大模型·产品经理·转行
风流倜傥唐伯虎12 小时前
Spring Boot Jar包生产级启停脚本
java·运维·spring boot
Yvonne爱编码12 小时前
JAVA数据结构 DAY6-栈和队列
java·开发语言·数据结构·python
Re.不晚12 小时前
JAVA进阶之路——无奖问答挑战1
java·开发语言
你这个代码我看不懂12 小时前
@ConditionalOnProperty不直接使用松绑定规则
java·开发语言
fuquxiaoguang12 小时前
深入浅出:使用MDC构建SpringBoot全链路请求追踪系统
java·spring boot·后端·调用链分析