📄 chap17.html
字号:
<!-- All material contained herein is copyright (c) McGraw-Hill Professional Books
All Rights Reserved. No use of this material may be made without express written
permission of the copyright holder. HTML conversions by Mega Space [barry@megaspace.com] -->
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
<TITLE>Understanding Digital Signatures: Inside the Java Virtual Machine
by Bill Venners - Beta Version</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<TABLE BORDER="0" WIDTH="100%">
<TR><TD><A HREF="http://www.pbg.mcgraw-hill.com/betabooks/stores.html" tppabs="http://www.pbg.mcgraw-hill.com/betabooks/stores.html" target="bottom"><IMG SRC="hotkey.gif" tppabs="http://www.pbg.mcgraw-hill.com/betabooks/images/hotkey.gif" ALIGN="LEFT" BORDER="0" WIDTH="40" HEIGHT="40" ALT="Orders"></A>
<IMG SRC="order_text.gif" tppabs="http://www.pbg.mcgraw-hill.com/betabooks/images/order_text.gif" WIDTH="103" HEIGHT="41" ALT="Orders"></TD>
<TD ALIGN="RIGHT"><A HREF="chap16.html" tppabs="http://www.pbg.mcgraw-hill.com/betabooks/venners/chap16.html"><IMG SRC="backward.gif" tppabs="http://www.pbg.mcgraw-hill.com/betabooks/images/backward.gif" BORDER="0" ALT="Backward" WIDTH="32" HEIGHT="32"></A> <A HREF="chap18.html" tppabs="http://www.pbg.mcgraw-hill.com/betabooks/venners/chap18.html"><IMG SRC="forward.gif" tppabs="http://www.pbg.mcgraw-hill.com/betabooks/images/forward.gif" BORDER="0" ALT="Forward" WIDTH="32" HEIGHT="32"></A></TD></TR>
<TR><TD COLSPAN="2"><A HREF="mailto:computing@mcgraw-hill.com"><IMG SRC="hotkey.gif" tppabs="http://www.pbg.mcgraw-hill.com/betabooks/images/hotkey.gif" ALIGN="LEFT" BORDER="0" WIDTH="40" HEIGHT="40" ALT="Comments"></A>
<IMG SRC="comment_text.gif" tppabs="http://www.pbg.mcgraw-hill.com/betabooks/images/comment_text.gif" WIDTH="73" HEIGHT="39" ALT="Comments"></TD></TR>
<TR><TD COLSPAN="2"><FONT FACE="ARIEL,HELVETICA" SIZE="-1"><I>© 1997 The McGraw-Hill Companies, Inc. All rights reserved. <BR>Any use of this Beta Book is subject to the rules stated in the <A HREF="http://www.mcgraw-hill.com/corporate/news_info/copyrttm.htm" tppabs="http://www.mcgraw-hill.com/corporate/news_info/copyrttm.htm" target="_top">Terms of Use</A>.</I></FONT><br>
<script language="javascript">
document.write("<a href='http://banners.linkbuddies.com/click.php?id=237296'><img src='http://banners.linkbuddies.com/image.php?id=237296&ref=" + document.referrer + "' width=468 height=60 alt='Click Here' border=0></a>");
</script></TD></TR>
</TABLE>
<HR>
<P><H1>Chapter Seventeen</H1></P>
<P><H2>Exceptions</H2></P>
<P>This chapter shows how exceptions are implemented in bytecodes. It describes the instruction for throwing an exception explicitly, explains exception tables, and shows how catch clauses work.</P>
<P>Accompanying this chapter on the CD-ROM is an applet that interactively illustrates the material presented in the chapter. The applet, named <I>Play Ball!</I>, simulates the Java Virtual Machine executing a method that throws and catches exceptions. At the end of this chapter, you will find a description of this applet and the bytecodes it executes.</P>
<H3><EM><P>Throwing and Catching Exceptions</P>
</EM></H3><P>Exceptions allow you to smoothly handle unexpected conditions that occur as your programs run. To demonstrate the way the Java Virtual Machine handles exceptions, consider a class named <CODE>NitPickyMath</CODE> that provides methods that perform addition, subtraction, multiplication, division, and remainder on integers. <CODE>NitPickyMath</CODE> performs these mathematical operations the same as the normal operations offered by Java's <FONT FACE="Courier New">+</FONT>, <FONT FACE="Courier New">-</FONT>, <FONT FACE="Courier New">*</FONT>, <FONT FACE="Courier New">/</FONT>, and <FONT FACE="Courier New">%</FONT> operators, except the methods in <CODE>NitPickyMath</CODE> throw checked exceptions on overflow, underflow, and divide-by-zero conditions. The Java Virtual Machine will throw an <CODE>ArithmeticException</CODE> on an integer divide-by-zero, but will not throw any exceptions on overflow and underflow. The exceptions thrown by the methods of <CODE>NitPickyMath</CODE> are defined as follows: </P>
<PRE><P><FONT FACE="Courier New">begin</FONT></P>
<FONT SIZE="2"><P></FONT><FONT FACE="Courier New">// On CD-ROM in file except/ex1/OverflowException.java
<P>class OverflowException extends Exception {</P>
<P>}</P>
</FONT><FONT SIZE="2"><P> </P></P>
<P></FONT><FONT FACE="Courier New">// On CD-ROM in file except/ex1/UnderflowException.java
<P>class UnderflowException extends Exception {</P>
<P>}</P>
</FONT><FONT SIZE="2"><P> </P></P>
<P></FONT><FONT FACE="Courier New">// On CD-ROM in file except/ex1/DivideByZeroException.java
<P>class DivideByZeroException extends Exception {</P>
<P>}</P>
</FONT><FONT SIZE="2"><P> </P></FONT><FONT FACE="Courier New">end</FONT></P></PRE>
<P>A simple method that catches and throws exceptions is the <CODE>remainder()</CODE> method of class <CODE>NitPickyMath</CODE>: </P>
<PRE><P><FONT FACE="Courier New">begin</FONT></P>
<FONT SIZE="2"><P></FONT><FONT FACE="Courier New">// On CD-ROM in file except/ex1/NitpickyMath.java
<P>class NitpickyMath {</P>
<P> </P>
<P> static int add(int a, int b)</P>
<P> throws OverflowException, UnderflowException {</P>
<P> </P>
<P> long longA = (long) a;</P>
<P> long longB = (long) b;</P>
<P> long result = a + b;</P>
<P> if (result </FONT> Integer.MAX_VALUE) {</P>
<P> throw new OverflowException();</P>
<P> }</P>
<P> if (result < Integer.MIN_VALUE) {</P>
<P> throw new UnderflowException();</P>
<P> }</P>
<P> return (int) result;</P>
<P> }</P>
<P> </P>
<P> static int subtract(int minuend, int subtrahend)</P>
<P> throws OverflowException, UnderflowException {</P>
<P> </P>
<P> long longMinuend = (long) minuend;</P>
<P> long longSubtrahend = (long) subtrahend;</P>
<P> long result = longMinuend - longSubtrahend;</P>
<P> if (result </FONT> Integer.MAX_VALUE) {</P>
<P> throw new OverflowException();</P>
<P> }</P>
<P> if (result < Integer.MIN_VALUE) {</P>
<P> throw new UnderflowException();</P>
<P> }</P>
<P> return (int) result;</P>
<P> }</P>
<P> </P>
<P> static int multiply(int a, int b)</P>
<P> throws OverflowException, UnderflowException {</P>
<P> </P>
<P> long longA = (long) a;</P>
<P> long longB = (long) b;</P>
<P> long result = a * b;</P>
<P> if (result </FONT> Integer.MAX_VALUE) {</P>
<P> throw new OverflowException();</P>
<P> }</P>
<P> if (result < Integer.MIN_VALUE) {</P>
<P> throw new UnderflowException();</P>
<P> }</P>
<P> return (int) result;</P>
<P> }</P>
<P> </P>
<P> static int divide(int dividend, int divisor)</P>
<P> throws OverflowException, DivideByZeroException {</P>
<P> </P>
<P> // Overflow can occur in division when dividing the</P>
<P> // negative integer of the largest possible magnitude</P>
<P> // (Integer.MIN_VALUE) by -1, because this would just flip</P>
<P> // the sign, but there is no way to represent that number</P>
<P> // in an int.</P>
<P> if ((dividend == Integer.MIN_VALUE) && (divisor == -1)) {</P>
<P> throw new OverflowException();</P>
<P> }</P>
<P> try {</P>
<P> return dividend / divisor;</P>
<P> }</P>
<P> catch (ArithmeticException e) {</P>
<P> throw new DivideByZeroException();</P>
<P> }</P>
<P> }</P>
<P> </P>
<P> static int remainder(int dividend, int divisor)</P>
<P> throws OverflowException, DivideByZeroException {</P>
<P> </P>
<P> // Overflow can occur in division when dividing the</P>
<P> // negative integer of the largest possible magnitude</P>
<P> // (Integer.MIN_VALUE) by -1, because this would just flip</P>
<P> // the sign, but there is no way to represent that number</P>
<P> // in an int.</P>
<P> if ((dividend == Integer.MIN_VALUE) && (divisor == -1)) {</P>
<P> throw new OverflowException();</P>
<P> }</P>
<P> try {</P>
<P> return dividend % divisor;</P>
<P> }</P>
<P> catch (ArithmeticException e) {</P>
<P> throw new DivideByZeroException();</P>
<P> }</P>
<P> }</P>
<P>}</P>
</FONT><FONT SIZE="2"><P> </P></FONT><FONT FACE="Courier New">end</FONT></P></PRE>
<P>The <CODE>remainder()</CODE> method simply performs the remainder operation (<FONT FACE="Courier New">%</FONT>) upon the two <EM><FONT FACE="Courier New">ints</FONT></EM> passed as arguments. The remainder operation throws an <CODE>ArithmeticException</CODE> if the divisor of the remainder operation is a zero. This method catches this <CODE>ArithmeticException</CODE> and throws a <CODE>DivideByZeroException</CODE>. </P>
<P>The difference between these two exceptions is that <CODE>DivideByZeroException</CODE> is <EM>checked</EM> and <CODE>ArithmeticException</CODE> is <EM>unchecked</EM>. Because the <CODE>ArithmeticException</CODE> is unchecked, a method need not declare this exception in a <FONT FACE="Courier New">throws</FONT> clause even though it might throw it. Any exceptions that are subclasses of either <CODE>Error</CODE> or <CODE>RuntimeException</CODE> are unchecked. (<CODE>ArithmeticException</CODE> is a subclass of <CODE>RuntimeException</CODE>.) By catching <CODE>ArithmeticException</CODE> and then throwing <CODE>DivideByZeroException</CODE>, the <CODE>remainder()</CODE> method forces its clients to deal with the possibility of a divide-by-zero exception, either by catching it or declaring <CODE>DivideByZeroException</CODE> in their own <FONT FACE="Courier New">throws</FONT> clauses. </P>
<P><CODE>javac</CODE> generates the following bytecode sequence for the <CODE>remainder</CODE> method: </P>
<PRE><P><FONT FACE="Courier New">begin</FONT></P>
<FONT SIZE="2"><P></FONT><FONT FACE="Courier New">// The main bytecode sequence for remainder():
<P> </P>
<P> 0 iload_0 // Push local variable 0 (arg passed as dividend)</P>
<P> // Push the minimum integer value</P>
<P> 1 ldc #1 <Integer -2147483648</FONT></P>
<P> // If the dividend isn't equal to the minimum integer,</P>
<P> // jump to the remainder calculation</P>
<P> 3 if_icmpne 19</P>
<P> </P>
<P> 6 iload_1 // Push local variable 1 (arg passed as divisor)</P>
<P> // Push -1</P>
<P> 7 iconst_m1</P>
<P> // If the divisor isn't equal to -1, jump</P>
<P> // to the remainder calculation</P>
<P> 8 if_icmpne 19</P>
<P> // This is an overflow case, so throw an exception</P>
<P> // Create a new OverflowException, push reference to</P>
<P> // it onto the stack</P>
<P>11 new #4 <Class OverflowException</FONT></P>
<P>14 dup // Make a copy of the reference</P>
<P> // Pop one copy of the reference and invoke the <init</FONT></P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -