“空语句”可能(不)抛出哪些Java错误和异常?

时间:2014-12-28 18:10:18

标签: java operating-system jvm virtual-machine jls

空语句可能抛出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 farInternalErrorOutOfMemoryErrorStackOverflowErrorUnknownError

3 个答案:

答案 0 :(得分:3)

编译器可能会删除包含" nothing"或来自字节码的空语句。字节码中的等价物与:

完全相同
// ....
A(); B(); C();

D(); E(); F();

G(); H(); I();

J(); K(); L();
// ....

当然,在执行过程中,可能会发生任何意外的Error(如UnknownError),并且通常不会在您的应用程序中处理它。

任何地方可能发生的最接近的异常(为了可能覆盖两个字节码指令之间的时间而强调)是asynchronous exceptions

  

大多数异常由于它们发生的线程的动作而同步发生,并且在程序中指定可能导致此类异常的点。相反,异步异常是一个可能在程序执行的任何时刻发生的异常。

     

异步异常仅在以下情况下发生:

     
      
  • 调用类stopThread的(已弃用)ThreadGroup方法。

         

    一个线程可以调用(不推荐使用的)stop方法来影响另一个线程或指定线程组中的所有线程。它们是异步的,因为它们可能在执行其他一个或多个线程的任何时刻发生。

  •   
  • Java虚拟机中的内部错误或资源限制,阻止它实现Java编程语言的语义。在这种情况下,抛出的异步异常是VirtualMethodError的子类的实例。

  •   

但同样,没有必要关心这种类型的异常(VirtualMethodError的子类),因为它们代表了JVM执行中的一个严重错误。例如,可能是由于用户使用 Ctrl + C 手动中断。在这种情况下,你无能为力。

答案 1 :(得分:2)

如果您不执行任何指令,则VM不太可能请求内存或用尽当前线程的堆栈空间。由于其他异常可能会被抛出,因为虚拟机中的任何一种状态都不合适,我想您应该始终期望发生InternalErrorUnknownError。因此,您不应该抓住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的子类;

是的,你可以这样说。我可能会用不同的措辞:任何指令都可以产生

  • JVM Instruction set为相关指令指定的例外情况
  • 类型VirtualMachineError
  • 的任何例外情况
  • 并且没有其他例外