|
|
|||
|
|
|
|
|
|
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
*/
|
|
|
|