空语句可能抛出java.lang.Throwable
的哪个子类?
通过短语"一个空的陈述",我引用"没有","分号&# 34;和"分号":
// ....
A(); B(); C();
try {
// nothing
} catch (java.lang.Throwable e) {
// which Throwable subclass might we see?
}
D(); E(); F();
try {
; // semi-colon
} catch (java.lang.Throwable e) {
// which Throwable subclass might we see?
}
G(); H(); I();
try {
; ; ;; ;;;;; ; ; ;;; ;; ;; ;; ;; ; ;; ; ;; // ... semi-colons
} catch (java.lang.Throwable e) {
// which Throwable subclass might we see?
}
J(); K(); L();
// ....
Throwable的哪些子类可能会在A();
和B();
之间或C();
和D();
之间或F();
之间抛出G();
或I();
和J();
之间?
或者更确切地说,哪些 Throwable的子类保证 不出现在这些语句之间?
The ones I know so far是InternalError
,OutOfMemoryError
,StackOverflowError
和UnknownError
。
答案 0 :(得分:3)
编译器可能会删除包含" nothing"或来自字节码的空语句。字节码中的等价物与:
完全相同// ....
A(); B(); C();
D(); E(); F();
G(); H(); I();
J(); K(); L();
// ....
当然,在执行过程中,可能会发生任何意外的Error
(如UnknownError
),并且通常不会在您的应用程序中处理它。
任何地方可能发生的最接近的异常(为了可能覆盖两个字节码指令之间的时间而强调)是asynchronous exceptions:
大多数异常由于它们发生的线程的动作而同步发生,并且在程序中指定可能导致此类异常的点。相反,异步异常是一个可能在程序执行的任何时刻发生的异常。
异步异常仅在以下情况下发生:
调用类
stop
或Thread
的(已弃用)ThreadGroup
方法。一个线程可以调用(不推荐使用的)
stop
方法来影响另一个线程或指定线程组中的所有线程。它们是异步的,因为它们可能在执行其他一个或多个线程的任何时刻发生。Java虚拟机中的内部错误或资源限制,阻止它实现Java编程语言的语义。在这种情况下,抛出的异步异常是
VirtualMethodError
的子类的实例。
但同样,没有必要关心这种类型的异常(VirtualMethodError
的子类),因为它们代表了JVM执行中的一个严重错误。例如,可能是由于用户使用 Ctrl + C 手动中断。在这种情况下,你无能为力。
答案 1 :(得分:2)
如果您不执行任何指令,则VM不太可能请求内存或用尽当前线程的堆栈空间。由于其他异常可能会被抛出,因为虚拟机中的任何一种状态都不合适,我想您应该始终期望发生InternalError
或UnknownError
。因此,您不应该抓住Throwable
而是Exception
,因为您不可能从错误中恢复 - 除非您正在创建自己的框架。
答案 2 :(得分:1)
此问题与您发布的the other question非常相似。我想我会在这里尝试解决这两个问题。
既然您参考了JVMS,我会假设您在正式回答之后,而正式答案是您的问题确实没有意义。 : - )
询问如何 JVM将执行一段Java源代码就像向数学家询问正确的计算10 + 10的方式。数学家可能会说" 如何来计算它没有定义"。同样,定义Java代码段含义的JLS没有详细说明如何执行它。
所以,首先让我稍微正式化你的问题:" 字节码中的哪一个(由javac
的参考实现发出)对应于给定的Java代码段可以{{ 1}}发生?"
这个问题可以说要简单得多。 relevant section of the JVMS说
当内部错误或资源限制阻止它实现本章中描述的语义时,Java虚拟机实现会抛出一个对象,该对象是类
VirtualMachineErrors
的子类的实例。该规范无法预测可能遇到内部错误或资源限制的位置,并且无法准确地确定何时可以报告它们。
因此,答案是:在任何两个字节码指令之间。
现在回到原来的问题:例如
这个代码段VirtualMethodError
编译为空程序,无法合理地抛出任何异常。
关于评论中的后续问题:
JLS 11.1.3应该被读作"
try { // nothing } catch (java.lang.Throwable e) { // which Throwable subclass might we see? }
的子类保证不会出现在字节码之间,除非它是Throwable
&#34的子类;
是的,你可以这样说。我可能会用不同的措辞:任何指令都可以产生
VirtualMachineError