⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compiling.doc.html

📁 A Java virtual machine instruction consists of an opcode specifying the operation to be performed, f
💻 HTML
📖 第 1 页 / 共 5 页
字号:
					// <code>Example.handleExc(LTestExc;)V</code>  11 	return				// Return after handling <code>TestExc</code>Exception table:   	From 	To 	Target 		Type     	0     	4     	5 		Class <code>TestExc</code></pre></blockquote>The invocation of <code>handleExc</code>, the contents of the <code>catch</code> clause, is also compiled like a normal method invocation. However, the presence of a <code>catch</code> clause causes the compiler to generate an exception table entry. The exception table for the <code>catchOne</code> method has one entry corresponding to the one argument (an instance of class <code>TestExc</code>) that the <code>catch</code> clause of <code>catchOne</code> can handle. If some value that is an instance of <code>TestExc</code> is thrown during execution of the instructions between indices 0 and 4 in <code>catchOne</code>, control is transferred to the Java virtual machine code at index 5, which implements the block of the <code>catch</code> clause. If the value that is thrown is not an instance of <code>TestExc</code>, the <code>catch</code> clause of <code>catchOne</code> cannot handle it. Instead, the value is rethrown to the invoker of <code>catchOne</code>.<p><a name="8030"></a>A <code>try</code> may have multiple <code>catch</code> clauses:<p><blockquote><pre><code>void catchTwo() {</code><code>    try {</code><code>        tryItOut();</code><code>    } catch (TestExc1 e) {</code><code>        handleExc(e);</code><code>    } catch (TestExc2 e) {</code><code>        handleExc(e);</code><code>    }</code><code>}</code></pre></blockquote>Multiple <code>catch</code> clauses of a given <code>try</code> statement are compiled by simply appending the Java virtual machine code for each <code>catch</code> clause one after the other and adding entries to the exception table, as shown:<p><blockquote><pre>Method <code>void catchTwo()</code>   0 	aload_0				// Begin <code>try</code> block   1 	invokevirtual #5 		// Method <code>Example.tryItOut()V</code>   4 	return				// End of <code>try</code> block; normal return   5 	astore_1			// Beginning of handler for <code>TestExc1</code>;					// Store thrown value in local variable 1   6 	aload_0				// Push <code>this</code>   7 	aload_1				// Push thrown value   8 	invokevirtual #7 		// Invoke handler method:					// <code>Example.handleExc(LTestExc1;)V</code>  11 	return				// Return after handling <code>TestExc1</code>  12 	astore_1			// Beginning of handler for <code>TestExc2</code>;					// Store thrown value in local variable 1  13 	aload_0				// Push <code>this</code>  14 	aload_1				// Push thrown value  15 	invokevirtual #7		// Invoke handler method:					// <code>Example.handleExc(LTestExc2;)V</code>  18 	return				// Return after handling <code>TestExc2</code>Exception table:	From 	To 	Target 		Type     	0     	4     	5   		Class <code>TestExc1</code>     	0     	4    	12   		Class <code>TestExc2</code></pre></blockquote>If during the execution of the <code>try</code> clause (between indices 0 and 4) a value is thrown that matches the parameter of one or more of the <code>catch</code> clauses (the value is an instance of one or more of the parameters), the first (innermost) such <code>catch</code> clause is selected. Control is transferred to the Java virtual machine code for the block of that <code>catch</code> clause. If the value thrown does not match the parameter of any of the <code>catch</code> clauses of <code>catchTwo</code>, the Java virtual machine rethrows the value without invoking code in any <code>catch</code> clause of <code>catchTwo</code>.<p><a name="8134"></a>Nested <code>try</code>-<code>catch</code> statements are compiled very much like a <code>try</code> statement with multiple <code>catch</code> clauses:<p><blockquote><pre><code>void nestedCatch() {</code><code>    try {</code><code>        try {</code><code>            tryItOut();</code><code>        } catch (TestExc1 e) {</code><code>            handleExc1(e);</code><code>        }</code><code>    } catch (TestExc2 e) {</code><code>        handleExc2(e);</code><code>    }</code><code>}</code></pre></blockquote>becomes<p><blockquote><pre>Method <code>void nestedCatch()</code>   0 	aload_0				// Begin <code>try</code> block   1 	invokevirtual #8 		// Method <code>Example.tryItOut()V</code>   4 	return				// End of <code>try</code> block; normal return   5 	astore_1			// Beginning of handler for <code>TestExc1</code>;					// Store thrown value in local variable 1   6 	aload_0				// Push <code>this</code>   7 	aload_1				// Push thrown value   8 	invokevirtual #7 		// Invoke handler method: 					// <code>Example.handleExc1(LTestExc1;)V</code>  11 	return				// Return after handling <code>TestExc1</code>  12 	astore_1			// Beginning of handler for <code>TestExc2</code>;					// Store thrown value in local variable 1  13 	aload_0				// Push <code>this</code>  14 	aload_1				// Push thrown value  15 	invokevirtual #6 		// Invoke handler method:					// <code>Example.handleExc2(LTestExc2;)V</code>  18 	return				// Return after handling <code>TestExc2</code>Exception table:   	From 	To 	Target 		Type     	0     	4     	5 		Class <code>TestExc1</code>     	0    	12    	12 		Class <code>TestExc2</code></pre></blockquote>The nesting of <code>catch</code> clauses is represented only in the exception table. When an exception is thrown, the first (innermost) catch clause that contains the site of the exception and with a matching parameter is selected to handle it. For instance, if the invocation of <code>tryItOut</code> (at index 1) threw an instance of <code>TestExc1</code>, it would be handled by the <code>catch</code> clause that invokes <code>handleExc1</code>. This is so even though the exception occurs within the bounds of the outer <code>catch</code> clause (catching <code>TestExc2</code>) and even though that outer <code>catch</code> clause might otherwise have been able to handle the thrown value.<p><a name="13784"></a>As a subtle point, note that the range of a <code>catch</code> clause is inclusive on the "from" end and exclusive on the "to" end (<a href="ClassFile.doc.html#1546">&#167;4.7.3</a>). Thus, the exception table entry for the <code>catch</code> clause catching <code>TestExc1</code> does not cover the return instruction at offset 4. However, the exception table entry for the <code>catch</code> clause catching <code>TestExc2</code> does cover the return instruction at offset 11. Return instructions within nested <code>catch</code> clauses are included in the range of instructions covered by nesting <code>catch</code> clauses.<p><a name="13789"></a><hr><h2>7.13    Compiling <code>finally</code></h2>Compilation of a <code>try</code>-<code>finally</code> statement is similar to that of <code>try-catch</code>. Prior to transferring control outside the <code>try</code> statement, whether that transfer is normal or abrupt, because an exception has been thrown, the <code>finally</code> clause must first be executed.For this simple example<p><blockquote><pre><code>void tryFinally() {</code><code>    try {</code><code>        tryItOut();</code><code>    } finally {</code><code>        wrapItUp();</code><code>    }</code><code>}</code></pre></blockquote>the compiled code is<p><blockquote><pre>Method <code>void tryFinally()</code>   0 	aload_0				// Beginning of <code>try</code> block   1	invokevirtual #6 		// Method <code>Example.tryItOut()V</code>   4 	jsr 14				// Call <code>finally</code> block   7 	return				// End of <code>try</code> block   8 	astore_1			// Beginning of handler for any throw   9 	jsr 14				// Call <code>finally</code> block  12 	aload_1				// Push thrown value  13 	athrow				// ...and rethrow the value to the invoker  14 	astore_2			// Beginning of <code>finally</code> block  15 	aload_0				// Push <code>this</code>  16 	invokevirtual #5 		// Method <code>Example.wrapItUp()V</code>  19 	ret 2				// Return from <code>finally</code> blockException table:   	From 	To 	Target 		Type	0    	4    	8   		any</pre></blockquote>There are four ways for control to pass outside of the <code>try</code> statement: by falling through the bottom of that block, by returning, by executing a <code>break</code> or <code>continue</code> statement, or by raising an exception. If <code>tryItOut</code> returns without raising an exception,control is transferred to the <code>finally</code> block using a jsr instruction. The jsr 14 instruction at index 4 makes a "subroutine call" to the code for the <code>finally</code> block at index 14 (the <code>finally</code> block is compiled as an embedded subroutine). When the <code>finally</code> block completes, the ret 2 instruction returns control to the instruction followingthe jsr instruction at index 4. <p><a name="9060"></a>In more detail, the subroutine call works as follows: The jsr instruction pushes the address of the following instruction (return at index 7) onto the operand stack before jumping. The astore_2 instruction that is the jump target stores the address on the operand stack into local variable 2. The code for the <code>finally</code> block (in this case the aload_0 and invokevirtual instructions) is run. Assuming execution of that code completes normally, the ret instruction retrieves the address from local variable 2 and resumes execution at that address. The return instruction is executed, and <code>tryFinally</code> returns normally.<p><a name="9071"></a>A <code>try</code> statement with a <code>finally</code> clause is compiled to have a special exception handler, one that can handle any exception thrown within the <code>try</code> statement. If <code>tryItOut</code> throws an exception, the exception table for <code>tryFinally</code> is searched for an appropriate exception handler. The special handler is found, causing execution to continue at index 8. The astore_1 instruction at index 8 stores the thrown value into local variable 1. The following jsr instruction does a subroutine call to the code for the <code>finally</code> block. Assuming that code returns normally, the aload_1 instruction at index 12 pushes the thrown value back onto the operand stack, and the following athrow instruction rethrows the value.<p><a name="9089"></a>Compiling a <code>try</code> statement with both a <code>catch</code> clause and a <code>finally</code> clause is more complex:<p><blockquote><pre><code>void tryCatchFinally() {</code><code>    try {</code><code>        tryItOut();</code><code>    } catch (TestExc e) {</code><code>        handleExc(e);</code><code>    } finally {</code><code>        wrapItUp();</code><code>    }</code><code>}</code></pre></blockquote>becomes<p><blockquote><pre>Method <code>void</code> <code>tryCatchFinally()</code>   0 	aload_0				// Beginning of <code>try</code> block   1 	invokevirtual #4 		// Method <code>Example.tryItOut()V</code>   4 	goto 16				// Jump to <code>finally</code> block   7 	astore_3			// Beginning of handler for <code>TestExc</code>;					// Store thrown value in local variable 3   8 	aload_0				// Push <code>this</code>   9 	aload_3				// Push thrown value  10 	invokevirtual #6 		// Invoke handler method:					// <code>Example.handleExc(LTestExc;)V</code>  13 	goto 16				// Huh???<a href="#13842"><sup>1</sup></a>  16 	jsr 26				// Call <code>finally</code> block  19 	return				// Return after handling <code>TestExc</code>  20 	astore_1			// Beginning of handler for exceptions					// other than <code>TestExc</code>, or exceptions					// thrown while handling <code>TestExc</code>  21 	jsr 26				// Call <code>finally</code> block  24 	aload_1				// Push thrown value...  25 	athrow				// ...and rethrow the value to the invoker  26 	astore_2			// Beginning of <code>finally</code> block  27 	aload_0				// Push <code>this</code>  28 	invokevirtual #5 		// Method <code>Example.wrapItUp()V</code>  31 	ret 2				// Return from <code>finally</code> blockException table:   	From 	To 	Target 		Type     	0     	4     	7 		Class <code>TestExc</code>     	0   	16    	20   		any</pre></blockquote><a name="9112"></a>If the <code>try</code> statement completes normally, the goto instruction at index 4 jumps to the subroutine call for the <code>finally</code> block at index 16. The <code>finally</code> block at index 26 is executed, control returns to the return instruction at index 19, and <code>tryCatchFinally</code> returns normally.<p><a name="9220"></a>If <code>tryItOut</code> throws an instance of <code>TestExc</code>, the first (innermost) applicable exception handler in the exception table is chosen to handle the exception. The code for that exception handler, beginning at index 7, passes the thrown value to <code>handleExc</code> and on its return makes the same subroutine call to the <code>finally</code> block at index 26 as in the normal case. If an exception is not thrown by <code>handleExc</code>, <code>tryCatchFinally</code> returns normally.<p><a name="9221"></a>If <code>tryItOut</code> throws a value that is not an instance of <code>TestExc</code> or if <code>handleExc</code> itself throws an exception, the condition is handled by the second entry in the exception table, which handles any value thrown between indices 0 and 16. That exception handler transfers control to index 20, where the thrown value is first stored in local variable 1. The code for the <code>finally</code> block at

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -