Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Bytecode basics

A first look at the bytecodes of the Java virtual machine

  • Print
  • Feedback

Page 10 of 10

 iconst_1          // Push int constant 1.
istore_1          // Pop into local variable 1, which is a: byte a = 1;
iconst_1          // Push int constant 1 again.
istore_2          // Pop into local variable 2, which is b: byte b = 1;
iload_1           // Push a (a is already stored as an int in local variable 1).
iload_2           // Push b (b is already stored as an int in local variable 2).
iadd              // Perform addition. Top of stack is now (a + b), an int.
int2byte          // Convert int result to byte (result still occupies 32 bits).
istore_3          // Pop into local variable 3, which is byte c: byte c = (byte) (a + b);
iload_3           // Push the value of c so it can be returned.
ireturn           // Proudly return the result of the addition: return c;


Conversion diversion: a JVM simulation

The applet below demonstrates a JVM executing a sequence of bytecodes. The bytecode sequence in the simulation was generated by javac for the Convert() method of the class shown below:

 class Diversion {
    static void Convert() {
        byte imByte = 0;
        int imInt = 125;
        while (true) {
            ++imInt;
            imByte = (byte) imInt;
            imInt *= -1;
            imByte = (byte) imInt;
            imInt *= -1;
        }
    }
}


The actual bytecodes generated by javac for Convert() are shown below:

 iconst_0          // Push int constant 0.
istore_0          // Pop to local variable 0, which is imByte: byte imByte = 0;
bipush 125        // Expand byte constant 125 to int and push.
istore_1          // Pop to local variable 1, which is imInt: int imInt = 125;
iinc 1 1          // Increment local variable 1 (imInt) by 1: ++imInt;
iload_1           // Push local variable 1 (imInt).
int2byte          // Truncate and sign extend top of stack so it has valid byte value.
istore_0          // Pop to local variable 0 (imByte): imByte = (byte) imInt;
iload_1           // Push local variable 1 (imInt) again.
iconst_m1         // Push integer -1.
imul              // Pop top two ints, multiply, push result.
istore_1          // Pop result of multiply to local variable 1 (imInt): imInt *= -1;
iload_1           // Push local variable 1 (imInt).
int2byte          // Truncate and sign extend top of stack so it has valid byte value.
istore_0          // Pop to local variable 0 (imByte): imByte = (byte) imInt;
iload_1           // Push local variable 1 (imInt) again.
iconst_m1         // Push integer -1.
imul              // Pop top two ints, multiply, push result.
istore_1          // Pop result of multiply to local variable 1 (imInt): imInt *= -1;
goto 5            // Jump back to the iinc instruction: while (true) {} 


The Convert() method demonstrates the manner in which the JVM converts from int to byte. imInt starts out as 125. Each pass through the while loop, it is incremented and converted to a byte. Then it is multiplied by -1 and again converted to a byte. The simulation quickly shows what happens at the edges of the valid range for the byte type.

The maximum value for a byte is 127. The minimum value is -128. Values of type int that are within this range convert directly to byte. However, as soon as the int gets beyond the valid range for byte, things get interesting.

The JVM converts an int to a byte by truncating and sign extending. The highest order bit, the "sign bit," of longs, ints, shorts, and bytes indicate whether or not the integer value is positive or negative. If the sign bit is zero, the value is positive. If the sign bit is one, the value is negative. Bit 7 of a byte value is its sign bit. To convert an int to a byte, bit 7 of the int is copied to bits 8 through 31. This produces an int that has the same numerical value that the int's lowest order byte would have if it were interpreted as a byte type. After the truncation and sign extension, the int will contain a valid byte value.

The simulation applet shows what happens when an int that is just beyond the valid range for byte types gets converted to a byte. For example, when the imInt variable has a value of 128 (0x00000080) and is converted to byte, the resulting byte value is -128 (0xffffff80). Later, when the imInt variable has a value of -129 (0xffffff7f) and is converted to byte, the resulting byte value is 127 (0x0000007f).

To drive the simulation, just press the "Step" button. Each press of the "Step" button will cause the JVM to execute one bytecode instruction. To start the simulation over, press the "Reset" button. There is a text area at the bottom of the applet that describes the next instruction to be executed. Happy clicking.

Click here for the source code of Conversion Diversion.

The small print: "Bytecode Basics" Article Copyright (c) 1996 Bill Venners. All rights reserved. "Conversion Diversion" Applet Copyright (c) 1996 Artima Software Company. All rights reserved.

About the author

Bill Venners provides custom software development and consulting services in Silicon Valley under under the name Artima Software Company. He has been object oriented for five years, primarily working in C++ on MS Windows. Before that he did a lot of C on Unix and assembly language on various microprocessors. He is currently focused on Java.
  • Print
  • Feedback

Resources
  • Previous Under The Hood articles:
  • The lean, mean virtual machine -- Gives an introduction to the Java virtual machine. Look here to see how the garbage collected heap fits in with the other parts of the JVM.
  • The Java class file lifestyle -- Gives an overview to the Java class file, the file format into which all Java programs are compiled.
  • Java's garbage-collected heap -- Gives an overview of garbage collection in general and the garbage-collected heap of the JVM in particular.