Java Virtual Machine by Jon Meyer and Troy Downing Unconfirmed error reports are from readers. They have not yet been approved or disproved by the author or editor and represent solely the opinion of the reader. This page was updated December 4, 2000. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification UNCONFIRMED errors and comments from readers: {3} para. 1, lines 2-3: "... purely interpreted languages (such as JavaScript, Lingo, Perl, and Tcl)" should be "... purely interpreted languages (such as JavaScript, Lingo, and Tcl)" (Perl is not purely interpreted.) {6} Table 1-1, last row: "int2short" should be "i2s" and "d2I" should be "d2i" {28} Table 2-1, last row: "private protected" combination is no longer allowed in the published Java standard {28} code sample 3, line 1: in "(Ljava/lang/String;)" the V (void return type) is missing {31} para.3 , line 1: "The type descriptor" should be "the type" ?32-33? comment from reader: Why does your implementation compute 10-i? Presumably it is so the final branch can be done against 0 instead of having to subtract from 10. But, you have to do the substraction earlier anyway for printing. Perhaps this is the code the compiler generated, but is a very confusing first example. I recommend storing i and subtracting from 10 at the end if you need to for the comparison. {36} All the places you reference variable 3, you should be referencing variable 2. [36] I think I have found a bug on page 36. The previous examples on pages 34 and 35 use the text: iinc 2 -1 iload_2 ifne Loop however, on page 36, the test uses local variable 3 instead of local variable 3. {38} the dup command had me stumped for a long time. Aside from the issue about not being able to store/load it (which you should comment on here), your comment threw me for a loop. It says 'dup the instance and call its constructor'. I assumed that that comment applied just to 'dup'! Even when I realized that the 'call its constructor' part applied to the following code, it still took me quite some time to realize you meant 'dup the reference'. Since I didn't know the JVM, I assumed that there was a command to duplicate an instance. It didn't make any sense, but there it was. Finally, explain that you must use dup, or else all references go away, and you need to keep one for the putfield command. {57} Table 3-5, row 3: "?2I" should be "?2i" (the "I" should be lowercase) {77} Table 4-3 makes a fairly serious error: it swaps the values of CONSTANT_String and CONSTANT_Class. An insignificant error: it reports the structure as a CONSTANT_Classref, when the Sun spec refers to it as a CONSTANT_Class. {77} CONSTANT_Class is called "CONSTANT_Classref" and its value is swapped with that of CONSTANT_String. The correct table appears on p.179. Also, I saw no mention of the fact that the count field for the constant table actually contains the count+1. Perhaps I missed it? {78} Table 4-4: Doesn't a CONSTANT_Utf8 take a word specifying the number of bytes in the ensuing string? {82} Table 4-5, title, "Constant pool of class "out"": this title actually belongs to Table 4-8 {87} 2nd P. You have the major/minor version mixed up somewhere. Either the byte code is wrong or the description is wrong. (87) Byte code: the spacing of the dashes is wrong below 'tag = 1' {87} Byte code: the second tag type is wrong. You have CONSTANT_Class, and it should be CONSTANT_FieldRef. (88) Table 4-8: I'd prefer the table entry numbers to be in hex so I could easily reference them from the byte code. As it is, I had to keep converting to decimal. Anyone that is reading this section in any detail better know hex, or forget it! {88} Table 4-8 entries 19 and 20; Table entry 19 should probably be changed as follows: Original: 19 | Class | name = "out" Corrected: 19 | Class | name = (8) "out" **** Table entry 20 should probably be changed as follows: Original: 20 | Utf8 | name = "java/lang/System" Corrected: 20 | Utf8 | bytes = "java/lang/System" ***** (89) 1st byte code: 2nd line spacing of dashes is wrong. ?89? Why doesn't the access_flags for this (and the following methods) also have ACC_SUPER? The description on page 84 specifically said that 'all modern compilers should set the ACC_SUPER bit ...' Either fix this or the description of the bit. (90) byte code: Spacing of dashes on 2nd line is messed up. {109} The authors state 'In Ansi C, a 64-bit integer is usually declared as a "long long"...'. If I recall correctly, 'long long' is not an ANSI C datatype, but a common extension. {140} Table 8-4, row -6: "d2I" should be "d2i" {146} text above Table 9-3: return value is either 0, or +1, OR -1 ?151? the example Point class seems a little strange. What kind of length are we figuring? Seems to me x and y are the cartesian coordinates of a point in 2-space. I could make more sense out of it if the class were named RightTriangle, where length calculates the hypotenuse, or if length took a reference to another Point as a parameter. {152} code sample 1, line 3: ".limit vars 3" should be ".limit locals 3" {173} last line, (byte1 << 8) + byte2, and {174} 2nd line, (byte1 << 24)..... These code fragments won't actually work as described. When Java applies the << and (I think) the + operators it is performing widening conversions on the byte values first. Because Java normally sign extends bytes values when it converts them to int or long values this code can result in negative numbers. One way of doing what you require is to use the & operator which (although I can't find this documented anyway - not even in the OReilly book on the language spec!) seems to do a widening conversion to an int or a long *without* extending the sign bit. So I would propose this instead: ((byte1 & 0xff) << 8) | (byte2 & 0xff) or this: ((byte1 & 0xff) << 8) + (byte2 & 0xff) {176} The text reads: "For interfaces, super_class is often (but not necessarily) the class java.lang.Object." According to Sun's Java Virtual Machine Specification posted on their web site (Section 4.1), , super_class must *always* be java.lang.Object. The fact that the O'Reilly book is careful enough to say that this isn't always the case is curious, but this appears to be a genuine error to me. {178} In the grammar, the should probably be a again (or v.v.)? {186} Under "Field Attributes": "Only one field attribute is currently recognized: the "ConstantValue" attribute. This gives the initial value of a -STATIC- field." I have written a code which disassembles .class bytecode. I found hat it's not STATIC but FINAL variable, whose value is stored by ConstanValue attribute. [202] The Exceptions list for the anewarray instruction is missing "OutOfMemoryError - insufficient memory to allocate the array". This is correct in new, newarray, and multianewarray. {223} the second-to-last sentence under "Description" of the dcmpl instruction should change from: "if either numbers is NaN, the integer 1 is pushed onto the stack" to: "if either number is NaN, the integer -1 is pushed onto the stack" {248} para. under "Description", line -1: "the integer 1" should be "the integer -1" {263} there is an error at the top of the page. It says that 'getstatic' pops an objectref off the stack, which is not true. The diagram on page 262 which shows the stack is, however, correct. {315} invokevirtual: the stack order of the runtime arguments is incorrect (wrong order). [322] 1st paragraph - Description; This mistake is in the ishr instruction - integer arithmetic shift right. The description states that value 1, the first value poped off the stack should be shifted right by the amount indicated in the low 5 bits of value 2. In fact, value 2 should be shifted right by the amount indicated in the low 5 bits of value 1. {386} There is a bug in the description of the tableswitch opcode: it should say (high-low+1), not vice-versa. {388} There is a bug in your description of the wide version of iinc: the operand should be a signed short. {chapter 4} I've just noticed that the Java 1.1 ClassLoader has a slightly different interface than the 1.0 ClassLoader (the defineClass method has been deprecated and a new method is in place). This will need to be reflected in Chapter 4 at some point. {page?} The java -verify option doesn't in fact turn on verification any more. Now you have to use AppletViewer, or write your own class loader, or use something akin to JavaRunner (see Java Security), or java.security.Main in Java 1.2