CS 152 - Lecture 23

Cover page image

Cay S. Horstmann

Compiling 2

BCEL

Why Bytecode Engineering?

Write a Class

Write a Method

Hello, World!

Constants and Variables

Arithmetic and Branches

Lab

???

Step 1: Install BCEL

  1. Download the BCEL library and unzip in a location of your choice.
  2. In Eclipse, make a Scala project bcellab
  3. Right-click on the project. Select Build Path → Add Libraries → User Library → User Libraries → New
  4. Give the name bcel-6.2 and click Ok
  5. Click on Add JARs and add the BCEL jar from the directory that you just created. Click OK
  6. Check bcel-6.2 and click Ok
  7. In the package explorer, expand your bcellab project. What children do you have?

Step 2: Hello, World!

  1. Hopefully, one of the children of your project was bcel-6.2 with grandchild bcel-6.2.jar
  2. Make a Scala object Main and copy/paste all the code from slides 4 - 6, in the right order.
  3. Build and run.
  4. Where is the HelloBCEL.class file located?
  5. Open a shell window; change to that directory. Run java HelloBCEL. What happens?
  6. What did you do to fix that problem?

Step 3: Count bits

  1. There is a simple recursive way of counting the bits in the binary representation of a nonnegative number: bits(n) = n % 2 + bits(n / 2). Your task is a BCEL program that generates a class Bits with a static method
    public static int bits(int n)

    and a main method that prints the result of bits(42).

    Let's get the printing out of the way first. Modify the previous program so that it calls java.lang.Math.abs(42) and prints that, rather than "Hello, World!". What modifications did you make to your program?

  2. Now implement the code that generates the bytecodes for the bits function. (There is no shame in writing the function in Java and peeking at the javap output. Only your teammate will know :-)) Remember to change java.lang.Math.abs to Bits.bits. What is the code that generates bits?

Step 4: Let's not be so divine

  1. To recurse may be divine, but SL3 has a native while loop, so we want to generate code for that. Your task is to change the code that generates the code for bits so that it no longer makes the recursive call but instead uses the loop
    int count = 0;
    while (n > 0) {
      count = count + n % 2;
      n = n / 2;
    } // Put a GOTO to the top of the loop here
    return count;

    What byte codes do you intend to generate?

  2. What is the BCEL code that generates them?

Step 5: Function Objects

The Java virtual machine does not have functions or closures as a native type. If we want to generate code for the JVM, we need to implement them as objects. Consider this code:

int fib(int n) // C-like language with nested functions
{
   int fibhelper(int i, int a, int b)
   {
      if (i == n) return b;
      else return fibhelper(i + 1, b, a + b);
   }
   fibhelper(1, 0, 1);
}

Here, fibhelper is an object with a method (which we will call invoke) and with an instance field for each free variable in its body (in this case, n). Every fibhelper(x, y, z) turns into a new FibHelper(n).invoke(x, y, z).

  1. Write the code for the fib method in Java. It needs to construct a fibhelper object and call its invoke method.
  2. Write the code for the class fibhelper in Java. (It needs one constructor and one invoke method.)
  3. What are the byte codes for the fib method? (Hint: javap)
  4. What are the byte codes for the fibhelper class? (Hint: javap)
  5. Write a BCEL program that generates the code for the main and fib functions in a program Fib, printing fib(30). Hint: Your program needs to generate two classes.