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

Logic and integer arithmetic

A look at the bytecodes of the Java virtual machine that perform logical and arithmetic operations

  • Print
  • Feedback

Page 4 of 5



Opcode Operand(s) Description


iand (none) boolean ands two ints


ior (none) boolean ors two ints


ixor (none) boolean xors two ints


The next table shows the opcodes that perform bitwise logical operations on longs.



Opcode Operand(s) Description


land (none) boolean ands two longs


lor (none) boolean ors two longs


lxor (none) boolean xors two longs


Logical results: A JVM simulation

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



class VulcanCounter {
    void incrementLogically() {
        int spock = 0;
        while (true) {
            int tempSpock = spock;
            for (int i = 0; i < 32; ++i) {
                int mask = 0x1 << i;
                if ((tempSpock & mask) == 0) {
                    tempSpock |= mask;
                    break;
                }
                else {
                    tempSpock &= mask;
                }
            }
            spock = tempSpock;
        }
    }
}


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



 0 iconst_0          // Push int constant 0.
 1 istore_0          // Pop to local variable 0: int spock = 0;
 2 iconst_0          // Push int constant 0.
 3 istore_1          // Pop to local variable 1: int i = 0;
 4 goto 33           // Jump unconditionally ()
 7 iconst_1          // Push int constant 1.
 8 iload_1           // Push local variable 1 (i).
 9 ishl              // Arithmetic shift left top int (i) by next to top int (1).
10 istore_2          // Pop to local variable 2: int mask = i << 0x1;
11 iload_0           // Push local variable 0 (spock).
12 iload_2           // Push local variable 2 (mask).
13 iand              // Bitwise AND top two ints: (spock & mask)
14 ifne 24           // Jump if top of stack is not equal to zero: if ((spock & mask) == 0) {
17 iload_0           // Push local variable 0 (spock).
18 iload_2           // Push local variable 2 (mask).
19 ior               // Bitwise OR top two ints (spock | mask)
20 istore_0          // Pop to local variable 0: spock |= mask;
21 goto 2            // Jump unconditionally (to top of while): break;
24 iload_0           // Push local variable 0 (spock).
25 iload_2           // Push local variable 2 (mask).
26 iconst_m1         // Push -1.
27 ixor              // Bitwise EXCLUSIVE-OR top two ints: mask
28 iand              // Bitwise AND top two ints: spock & (mask)
29 istore_0          // Pop to local variable 2: spock &= mask;
30 iinc 1 1          // Increment local variable 1 by 1: ++i
33 iload_1           // Push local variable 1 (i).
34 bipush 32         // Push integer constant 32.
36 if_icmplt 7       // Jump (to top of for) if next to top integer is less than top
                     //      integer: i < 32
39 goto 2            // Jump unconditionally (to top of while).


The incrementItLogically() method repeatedly increments an int without using the + or ++ operators. Only logical operators &, |, and are used. An increment is accomplished by searching through the bits of the current int, starting with the lowest order bit, and turning ones to zeros. As soon as a one is encountered in the current int, it is changed to zero and the search stops. The resultant int now represents the old int incremented by one. The process is started again on the new int. Each incremented number is stored in the spock variable. Spock is local variable zero in the compiled bytecodes, so you can watch local variable zero count 0, 1, 2, 3, and so on.

  • 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 Java virtual machine in particular.
  • Bytecode basics -- Introduces the bytecodes of the JVM, and discusses primitive types, conversion operations, and stack operations in particular.
  • Floating point arithmetic -- Discusses the Java virtual machine's floating point support and the bytecodes that perform floating point arithmetic.