If I understand your question correctly, the following code
public class Example {
public static void main(String[] args) {
try {
otherMethod();
}
catch (Exception e) {}
try {
otherMethod();
someMethod();
}
catch (SQLException e) {}
catch (IOException e) {}
}
public static void someMethod() throws IOException {throw new IOException();}
public static void otherMethod() throws SQLException, IOException {}
}
produces the following (excerpt of human readable version of) byte code.
// main method
0: invokestatic #2 // Method otherMethod:()V
3: goto 7
6: astore_1
7: invokestatic #2 // Method otherMethod:()V
10: invokestatic #4 // Method someMethod:()V
13: goto 21
16: astore_1
17: goto 21
20: astore_1
21: return
Exception table:
from to target type
0 3 6 Class java/lang/Exception
7 13 16 Class java/sql/SQLException
7 13 20 Class java/io/IOException
You'll notice the Exception table
. This constructs instructs the VM that if an exception of type type
happens between the instruction from from
to to
, then it must goto
instruction (offset) target
. It also instructs it to push the Exception
reference on the stack so that its value can be copied and bound to the parameter in the catch
block.
You also have this piece relating to the throw
statement above.
// someMethod method
0: new #6 // class java/io/IOException
3: dup
4: invokespecial #7 // Method java/io/IOException."<init>":()V
7: athrow
The instruction athrow
does the following
throws an error or exception (notice that the rest of the stack is
cleared, leaving only a reference to the Throwable)
The JVM explains what happens
The objectref must be of type reference and must refer to an object
that is an instance of class Throwable or of a subclass of Throwable.
It is popped from the operand stack. The objectref is then thrown by
searching the current method (§2.6) for the first exception handler
that matches the class of objectref, as given by the algorithm in
§2.10.
If an exception handler that matches objectref is found, it contains
the location of the code intended to handle this exception. The pc
register is reset to that location, the operand stack of the current
frame is cleared, objectref is pushed back onto the operand stack, and
execution continues.
If no matching exception handler is found in the current frame, that
frame is popped. If the current frame represents an invocation of a
synchronized method, the monitor entered or reentered on invocation of
the method is exited as if by execution of a monitorexit instruction
(§monitorexit). Finally, the frame of its invoker is reinstated, if
such a frame exists, and the objectref is rethrown. If no such frame
exists, the current thread exits.
So stack frames keep getting popped until one is found that can handle the thrown exception.
How will this actually be implemented by the compiler. Where is the
check for the exception actually put in the assembly code generated?
The compiler generates the bytecode above. There is no check for an exception, only byte code instructions. The athrow
will instruct the VM to perform the task of what we call throwing an exception, which will result in popping the stack, searching exception tables in the current stack frame, etc.