CSc 620 - Debugging, Profiling, Tracing, and Visualizing Programs
2 : Java Bytecode -- BCEL

Christian Collberg

Department of Computer Science

University of Arizona

1 BCEL

2 Getting started

To open a class file for editing you do the following:

org.apache.bcel.classfile.ClassParser p = 
   new org.apache.bcel.classfile.ClassParser(classFile);
 org.apache.bcel.classfile.JavaClass jc = p.parse()
org.apache.bcel.generic.ClassGen cg = 
   new org.apache.bcel.generic.ClassGen(jc);
org.apache.bcel.generic.ConstantPoolGen cp = 
   new org.apache.bcel.generic.ConstantPoolGen(
              jc.getConstantPool());

3 Getting started...

4 Finishing up

   org.apache.bcel.classfile.JavaClass jc1 = 
      cg.getJavaClass();
   jc1.setConstantPool(cp.getFinalConstantPool());
   jc1.dump(classFile1);

5 Editing a Method

org.apache.bcel.generic.ConstantPoolGen cp = ...;
org.apache.bcel.generic.ClassGen cg = ...;

org.apache.bcel.classfile.Method method = 
   cg.containsMethod(methodName, methodSignature);
org.apache.bcel.generic.MethodGen mg = 
   new org.apache.bcel.generic.MethodGen(method,cname,cp);

6 Editing Instructions

org.apache.bcel.generic.MethodGen mg = ...;

org.apache.bcel.generic.InstructionList il = 
   mg.getInstructionList();
org.apache.bcel.generic.InstructionHandle[] ihs = 
   il.getInstructionHandles();
for(int i=0; i < ihs.length; i++) {
   org.apache.bcel.generic.InstructionHandle ih = ihs[i];
   org.apache.bcel.generic.Instruction instr = 
         ih.getInstruction();
}

7 Editing Instructions...

8 Changing an Instruction

org.apache.bcel.generic.Instruction inst = ...;
org.apache.bcel.generic.InstructionHandle ih = ...;

if (inst instanceof org.apache.bcel.generic.INVOKESTATIC){
   org.apache.bcel.generic.INVOKESTATIC call =
     (org.apache.bcel.generic.INVOKESTATIC) inst;
   String className  = call.getClassName(cp);
   String methodName = call.getMethodName(cp);
   String methodSig  = call.getSignature(cp);

   ih.setInstruction(new org.apache.bcel.generic.NOP());
}

9 Local variables

10 Local variables...

   void P() {
      int x= 5;
      System.out.println(x);
      float y=5.6;
      System.out.println(y);
   }

11 Local variables...

org.apache.bcel.generic.Type T = ...;

org.apache.bcel.generic.LocalVariableGen lg = 
   mg.addLocalVariable(localName, T, null, null);
int localIndex = lg.getIndex();

// push something here
org.apache.bcel.generic.Instruction store = 
   new org.apache.bcel.generic.ASTORE(localIndex);

org.apache.bcel.generic.InstructionHandle start = ...;
lg.setStart(start);

12 Local variables...

   org.apache.bcel.generic.LocalVariableGen lg = 
      mg.addLocalVariable(localName, T, null, null);
   ...
   org.apache.bcel.generic.InstructionHandle start = ...;
   lg.setStart(start);

13 Example 1: Creating a New Class

int flags = org.apache.bcel.Constants.ACC_PUBLIC;
String class_name = "MyClass";
String file_name = "MyClass.java";
String super_class_name = "java.lang.Object";
String[] interfaces = {};

org.apache.bcel.generic.ClassGen cg = 
   new org.apache.bcel.generic.ClassGen(
      class_name, super_class_name, file_name,
      flags, interfaces);

14 Example 1...

org.apache.bcel.generic.ConstantPoolGen cp = 
   cg.getConstantPool();

org.apache.bcel.generic.Type field_type = 
   org.apache.bcel.generic.Type.INT;
String field_name = "field1"; 

org.apache.bcel.generic.FieldGen fg =
   new org.apache.bcel.generic.FieldGen(
      access_flags, field_type, field_name, cp);
cg.addField(fg.getField());

15 Example 1 - Creating a Method

int method_access_flags = 
   org.apache.bcel.Constants.ACC_PUBLIC | 
   org.apache.bcel.Constants.ACC_STATIC;

org.apache.bcel.generic.Type return_type = 
   org.apache.bcel.generic.Type.VOID;

org.apache.bcel.generic.Type[] arg_types = 
   org.apache.bcel.generic.Type.NO_ARGS;
String[] arg_names = {};

16 Example 1 - Creating a Method...

String method_name = "method1";
String class_name = "MyClass";

org.apache.bcel.generic.InstructionList il = 
   new org.apache.bcel.generic.InstructionList();
il.append(
   org.apache.bcel.generic.InstructionConstants.RETURN);

org.apache.bcel.generic.MethodGen mg = 
   new org.apache.bcel.generic.MethodGen(
      method_access_flags, return_type,  arg_types,
      arg_names, method_name, class_name, il, cp);

mg.setMaxStack();
cg.addMethod(mg.getMethod());

17 Example 1 - Creating a Method...

18 Branches

org.apache.bcel.generic.InstructionList il = ...;
 
org.apache.bcel.generic.IFNULL branch = 
   new org.apache.bcel.generic.IFNULL(null);
il.append(branch);
   ...

19 Branches...

   org.apache.bcel.generic.InstructionHandle h = 
      il.append(new org.apache.bcel.generic.NOP());
   branch.setTarget(h);

20 Exceptions

org.apache.bcel.generic.InstructionList il = ...;
org.apache.bcel.generic.MethodGen mg = ...;
String exception = "java.lang.Exception";

org.apache.bcel.generic.InstructionHandle start_pc =
   il.append(new org.apache.bcel.generic.NOP());

// The code that builds the try-body goes here.

// Code to jump out of the try-block:
org.apache.bcel.generic.GOTO branch = 
   new org.apache.bcel.generic.GOTO(null);

21 Exceptions...

org.apache.bcel.generic.InstructionHandle end_pc =
   il.append(branch);

// Pop exception off stack when entering catch block.
org.apache.bcel.generic.InstructionHandle handler_pc =
    il.append(new org.apache.bcel.generic.POP());

// The code that builds the catch-body goes here.

// Add a NOP after the exception handler. This is 
// where we will jump after we're through with the
// try-block.
org.apache.bcel.generic.InstructionHandle next_pc =
    il.append(new org.apache.bcel.generic.NOP());
branch.setTarget(next_pc);

22 Exceptions...

org.apache.bcel.generic.ObjectType catch_type =
   new org.apache.bcel.generic.ObjectType(exception);

org.apache.bcel.generic.CodeExceptionGen eg =
   mg.addExceptionHandler(
      start_pc, end_pc, handler_pc, catch_type);

23 Types

 BaseType Type Interpretation
 B byte signed 8-bit integer
 C char Unicode character
 D double 64-bit floating point value
 F float 32-bit floating point value
 I int 32-bit integer
 J long 64-bit integer
 L<classname>; reference instance of class <classname>
 S short signed 16-bit integer
 Z boolean true pr false
 [ reference one array dimension
 V   void
 (BaseType*)BaseType   method descriptor

24 Types...

   org.apache.bcel.generic.Type return_type = 
      org.apache.bcel.generic.Type.VOID;
   org.apache.bcel.generic.Type[] arg_types   = 
      new org.apache.bcel.generic.Type[] { 
         new org.apache.bcel.generic.ArrayType(
            org.apache.bcel.generic.Type.STRING, 1)
      };

25 Types...

26 Types...

27 Types...

28 Types...

String S = "(Ljava/lang/String;I)V;";
org.apache.bcel.generic.Type[] arg_types =
   org.apache.bcel.generic.Type.getArgumentTypes(S);
org.apache.bcel.generic.Type return_type =
   org.apache.bcel.generic.Type.getReturnType(S);
String M = 
   org.apache.bcel.generic.Type.getMethodSignature(
      return_type, arg_types);

29 Types...

30 Static Method Calls

String className  = ...;
String methodName = ...;
String signature  = ...;

org.apache.bcel.generic.InstructionList il = ...;
org.apache.bcel.generic.ConstantPoolGen cp = ...;

31 Static Method Calls...

// Generate code that pushes the actual 
// arguments of the call.

int index = 
   cp.addMethodref(className,methodName,signature);
org.apache.bcel.generic.INVOKESTATIC call = 
    new org.apache.bcel.generic.INVOKESTATIC(index);
il.append(call);

32 Virtual Method Calls

// Generate code pushing the object on the stack.
// Generate code pushing the actual arguments.

int index = 
   cp.addMethodref(className,methodName,signature);
org.apache.bcel.generic.INVOKEVIRTUAL s = 
    new org.apache.bcel.generic.INVOKEVIRTUAL(index);
il.append(call);

33 Example 2: List.java

public class List {
public static void main(String args[]) 
           throws java.io.IOException {
   String classFile = args[0];
   String className = 
     classFile.substring(
        0,classFile.length()-".class".length());

   org.apache.bcel.classfile.ClassParser p = 
      new org.apache.bcel.classfile.ClassParser(classFile);

   org.apache.bcel.classfile.JavaClass jc = p.parse();

   org.apache.bcel.generic.ClassGen cg = 
      new org.apache.bcel.generic.ClassGen(jc);

34 Example 2: List.java

   org.apache.bcel.classfile.ConstantPool cp = 
       jc.getConstantPool();

   org.apache.bcel.generic.ConstantPoolGen cpg = 
      new org.apache.bcel.generic.ConstantPoolGen(cp);

   org.apache.bcel.classfile.Method[] methods = 
      cg.getMethods();

   for(int m=0; m<methods.length; m++) {
      org.apache.bcel.generic.MethodGen mg = 
         new org.apache.bcel.generic.MethodGen(
            methods[m],className,cpg);
      System.out.println("\nMETHOD: " + 
         mg.getClassName() + "." + 
         mg.getName() + ":" + mg.getSignature());

35 Example 2: List.java

      org.apache.bcel.generic.InstructionList il = 
         mg.getInstructionList();
      org.apache.bcel.generic.InstructionHandle[] ihs = 
         il.getInstructionHandles();

      int pc = 0;
      for(int i=0; i < ihs.length; i++) {
         org.apache.bcel.generic.InstructionHandle ih = ihs[i];
         org.apache.bcel.generic.Instruction instr = 
            ih.getInstruction();
         System.out.println(pc + " : " + instr.toString(cp)); 
         pc += instr.getLength();
      }
   }
}

}

36 Readings and References



Christian S. Collberg
2005-08-24