![]() |
|||
![]() ![]() |
![]() |
|
![]() |
ExceptionsExceptions are implemented mostly through the opcodes that youve already encountered, such as new, astore, and goto. The one new opcode that you need to throw exceptions is athrow. The opcode athrow pops a reference to a Throwable object (an instance of a subclass of java.lang.Error or java.lang.Exception) from the stack and then searches the current frame for the nearest catch clause that catches that type of Throwable. If a catch clause is found that catches this exception, then control moves into the catch clause and program execution resumes there. If, on the other hand, no catch clause is found that can handle this type of exception or error, then the current thread terminates. Catch clauses do not require any special opcodes. They are just different areas of the byte code for a method. The ExceptionsTable attribute for a method stores the addresses of the catch clauses that handle different classes of exceptions. The finally clauses do require some extra instructions, however. The jsr and jsr_w instructions move flow control from one place in the byte code into the finally clause. The finally clause is terminated with a ret instruction that moves flow control back. Thus, multiple try and catch clauses can all share one finally clause, and the code does not need to be duplicated. Consider Listing 5-10. This program exercises nearly all of Javas exception mechanisms. In the catchException() method, a runtime exception is thrown and caught without an explicit throw statement. In throwRuntimeException, a RuntimeException is constructed and thrown with a throw statement. In throwCheckedException(), a checked exception is declared in a throws clause and thrown by a throw statement. Last, finallyTest() catches the exception thrown by throwCheckedException() and uses a finally clause. Look at how these compile to byte codes. Listing 5-10 The ExceptionTest program class ExceptionTest { public static void main(String[] args) { ExceptionTest et = new ExceptionTest(); et.catchException(); et.finallyTest(); } void catchException() { int[] a = new int[5]; try { a[5] = 7; } catch (ArrayIndexOutOfBoundsException e) { System.err.println(e); } } void throwRuntimeException() { throw new NullPointerException(This is a test); } void throwCheckedException() throws InterruptedException { throw new InterruptedException(This is a test); } The ExceptionTest program void finallyTest() { try { throwCheckedException(); } catch (Exception e) { System.err.println(e); } finally { System.out.println(All done!); } } } Listing 5-11 has the compiled (but disassembled) byte code form of this program. Listing 5-11 ExceptionTest disassembled import java.io.PrintStream; class ExceptionTest extends java.lang.Object { public static void main(java.lang.String[]) { 0 new 10 3 dup 4 invokespecial 12 7 astore_1 8 aload_1 9 invokevirtual 16 12 aload_1 13 invokevirtual 15 16 return } void catchException() { 0 iconst_5 1 newarray 10 3 astore_1 4 aload_1 5 iconst_5 6 bipush 7 8 iastore 9 return 10 astore_2 11 getstatic 17 14 aload_2 15 invokevirtual 20 18 return } void throwRuntimeException() { 0 new 5 3 dup 4 ldc 1 6 invokespecial 21 9 athrow } void throwCheckedException() throws java.lang.InterruptedException { 0 new 7 3 dup 4 ldc 1 6 invokespecial 14 9 athrow } void finallyTest() { 0 aload_0 1 invokevirtual 13 4 goto 14 7 astore_3 8 getstatic 17 11 aload_3 12 invokevirtual 20 15 goto 3 18 jsr 10 21 return 22 astore_1 23 jsr 5 26 aload_1 27 athrow 28 astore_2 29 getstatic 18 32 ldc 2 34 invokevirtual 19 37 ret 2 } void <init>() { 0 aload_0 1 invokespecial 11 4 return } } /* 1: String 37 2: String 63 3: ClassInfo 67 4: ClassInfo 58 5: ClassInfo 42 6: ClassInfo 43 7: ClassInfo 66 8: ClassInfo 62 9: ClassInfo 52 10: ClassInfo 57 11: MethodRef ClassIndex: 9; NameAndTypeIndex: 28 12: MethodRef ClassIndex: 10; NameAndTypeIndex: 28 13: MethodRef ClassIndex: 10; NameAndTypeIndex: 26 14: MethodRef ClassIndex: 7; NameAndTypeIndex: 23 15: MethodRef ClassIndex: 10; NameAndTypeIndex: 22 16: MethodRef ClassIndex: 10; NameAndTypeIndex: 27 17: FieldRef ClassIndex: 8; NameAndTypeIndex: 30 18: FieldRef ClassIndex: 8; NameAndTypeIndex: 29 19: MethodRef ClassIndex: 6; NameAndTypeIndex: 25 20: MethodRef ClassIndex: 6; NameAndTypeIndex: 24 21: MethodRef ClassIndex: 5; NameAndTypeIndex: 23 22: NameAndType NameIndex: 36; DescriptorIndex: 69 23: NameAndType NameIndex: 60; DescriptorIndex: 51 24: NameAndType NameIndex: 31; DescriptorIndex: 38 25: NameAndType NameIndex: 31; DescriptorIndex: 51 26: NameAndType NameIndex: 33; DescriptorIndex: 69 27: NameAndType NameIndex: 53; DescriptorIndex: 69 28: NameAndType NameIndex: 60; DescriptorIndex: 69 29: NameAndType NameIndex: 50; DescriptorIndex: 61 30: NameAndType NameIndex: 39; DescriptorIndex: 61 31: UTF8 println 32: UTF8 this 33: UTF8 throwCheckedException 34: UTF8 Ljava/lang/ArrayIndexOutOfBoundsException; 35: UTF8 a 36: UTF8 finallyTest 37: UTF8 This is a test 38: UTF8 (Ljava/lang/Object;)V 39: UTF8 err 40: UTF8 ConstantValue 41: UTF8 LocalVariableTable 42: UTF8 java/lang/NullPointerException 43: UTF8 java/io/PrintStream 44: UTF8 Exceptions 45: UTF8 LineNumberTable 46: UTF8 SourceFile 47: UTF8 LocalVariables 48: UTF8 Code 49: UTF8 throwRuntimeException 50: UTF8 out 51: UTF8 (Ljava/lang/String;)V 52: UTF8 java/lang/Object 53: UTF8 catchException 54: UTF8 ExceptionTest.java 55: UTF8 main 56: UTF8 Ljava/lang/Exception; 57: UTF8 ExceptionTest 58: UTF8 java/lang/ArrayIndexOutOfBoundsException 59: UTF8 ([Ljava/lang/String;)V 60: UTF8 <init> 61: UTF8 Ljava/io/PrintStream; 62: UTF8 java/lang/System 63: UTF8 All done! 64: UTF8 et 65: UTF8 LExceptionTest; 66: UTF8 java/lang/InterruptedException 67: UTF8 java/lang/Exception 68: UTF8 [I 69: UTF8 ()V 70: UTF8 args 71: UTF8 [Ljava/lang/String; 72: UTF8 e */
|
![]() |
|