Search code examples
jvmtry-catchbytecode

Which JVM instructions cannot throw?


Are there any JVM instructions which are guaranteed not to throw?

If I understand correctly, the spec more or less says that a VirtualMachineError may be thrown at any time. So these two methods may not necessarily behave the same in all situations:

int foo() {
  try { return 1; }
  catch (Throwable t) { return 2; }
}

int bar() { return 1; }

Are there any cases (except if the try block is empty) where the behavior is guaranteed to stay the same after removing a try-catch?


Solution

  • You are asking the wrong question. If you expect a VirtualMachineError to be thrown, you can’t expect the behavior to be guaranteed to stay the same, regardless of whether there is a try … catch or not.

    To stay at your example:

    try { return 1; }
    catch (Throwable t) { return 2; }
    

    For this code, there will be an exception handler for the two byte code instructions iload_1, ireturn. This implies that if a VirtualMachineError is raised right before the iload_1 instruction or right after the JVM encountered the ireturn instruction, the error won’t be catched. And nobody can tell apart that situation from the situation when the the exception handler has been removed and the error is raised in-between these instructions.

    Compare with The Java® Virtual Machine Specification, Java SE 8 Edition §2.10. Exceptions:

    A Java Virtual Machine may permit a small but bounded amount of execution to occur before an asynchronous exception is thrown. This delay is permitted to allow optimized code to detect and throw these exceptions at points where it is practical to handle them while obeying the semantics of the Java programming language.

    So for the case of the VirtualMachineError, the absence of the exception handler would make no difference, no one can notice it and the JVM might defer the error anyway depending on the internal state of code optimization. A different case is the possibility of ireturn throwing an IllegalMonitorStateException.

    After all, the question is what you are going to optimize. Exception handlers normally have no performance impact as the JVM doesn’t touch them as long as no exception is there to be handled.