// File RTCG4B.java --- the power example // sestoft@itu.dk * 2002-09-17 // Using BCEL from http://jakarta.apache.org/bcel/ import org.apache.bcel.*; // Constants import org.apache.bcel.classfile.*; // JavaClass import org.apache.bcel.generic.*; // ClassGen, MethodGen, instructions import java.io.*; public class RTCG4B { public static void main(String[] args) throws IOException, NoSuchMethodException, IllegalAccessException, java.lang.reflect.InvocationTargetException { int count = Integer.parseInt(args[0]); int n = 16; ClassGen cg = new ClassGen("MyClass", "java.lang.Object", "", Constants.ACC_PUBLIC | Constants.ACC_SUPER, null); ConstantPoolGen cp = cg.getConstantPool(); { // Build: public static int MyPower(int x) { ... } InstructionList il = new InstructionList(); MethodGen mg = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC, Type.INT, new Type[] { Type.INT }, new String[] { "x" }, "MyPower", "MyClass", il, cp); PowerGen(il, mg, n); mg.setMaxStack(); cg.addMethod(mg.getMethod()); } // Get the generated class JavaClass clazz = cg.getJavaClass(); // Output class in human-readable format: System.out.println(clazz); // Output method body in human-readable format: System.out.println(clazz.getMethods()[0].getCode()); // Output class file to class file on disk: clazz.dump("MyClass.class"); // Output class file to array: byte[] classFile = clazz.getBytes(); // Load the class file from byte array into the JVM Class ty = new ArrayClassLoader().loadClass("MyClass", classFile); // Get the MyMethod(int): java.lang.reflect.Method m = ty.getMethod("MyPower", new Class[] { int.class }); // Call the method: System.out.println(m.invoke(null, new Object[] { new Integer(3) })); } public static int Power(int n, int x) { int p; p = 1; while (n > 0) { if (n % 2 == 0) { x = x * x; n = n / 2; } else { p = p * x; n = n - 1; } } return p; } public static void PowerGen(InstructionList il, MethodGen mg, int n) { final int x = 0; // x is local var 0 LocalVariableGen varp = mg.addLocalVariable("p", Type.INT, null, null); final int p = varp.getIndex(); varp.setStart(il.append(new ICONST(1))); il.append(new ISTORE(p)); // p = 1; while (n > 0) { if (n % 2 == 0) { il.append(new ILOAD(x)); // load x il.append(new ILOAD(x)); // load x il.append(new IMUL()); il.append(new ISTORE(x)); // x = x * x n = n / 2; } else { il.append(new ILOAD(p)); // load p il.append(new ILOAD(x)); // load x il.append(new IMUL()); il.append(new ISTORE(p)); // p = p * x n = n - 1; } } il.append(new ILOAD(p)); il.append(new IRETURN()); // return p; } } // This is needed because defineClass is protected in java.lang.ClassLoader: class ArrayClassLoader extends ClassLoader { public Class loadClass(String name, byte[] classFile) { return defineClass(name, classFile, 0, classFile.length); } }