Contains classes to generate, read, write, and print Java bytecode in the form of `.class` files.

It is used by Kawa to compile Scheme into bytecodes; it should be useful for other languages that need to be compiled into Java bytecodes. (An interesting exercise would be an interactive Java expression evaluator.) The classes here are relatively low-level. If you want to use them to generate bytecode from a high-level language, it would be easier to use the gnu.expr package, which works at the expression level, and handles all the code-generation for you.

The most important class is `ClassType`. This contains information about a single class. Note that the difference between `ClassType` and `java.lang.Class` is that the latter can only represent existing classes that have been loaded into the Java VM; in contrast, `ClassType` can be used to build new classes incrementally and on the fly. A `ClassType` can also wrap a `java.lang.Class`, or data read in from a `.class` file. Use `ClassType.make` to refer to existing classes and `new ClassType` to refer to classes you're generating.

A `ClassType` has a list of `Field` objects; new ones can be added using the various `addField` methods. A `ClassType` manages a `ConstantPool`. A `ClassType` also has a list of `Method` objects; new ones can be created by the various `addMethod` objects.

Calling `Method.startCode` gives you a `CodeAttr` object you can use to emit bytecodes for that method.

Once you have finished generating a `ClassType`, you can write it to a `.class` file with the `writeToFile` method. You can also make a byte array suitable for `ClassLoader.defineClass` using the `writeToArray` method. This is useful if you want to compile and immediately load a class, without going via disk.

You can print out the contents of a `ClassType` in human-readable form using the class `ClassTypeWriter`. This prints a fair bit of information of the generated class, including dis-assembling the code of the methods.

You can also build a `ClassType` by reading it from an existing `.class` file by using a `ClassFileInput` class. This reads the constant pool, the fields, methods, superclass, and interfaces. The `gnu.bytecode.dump` class has a `main` method that prints out the information in a named class file, which you can use as a replacement for `javap(1)`.

## A Simple Example

Here's a complete example showing the basics. If this was really all you wanted to do, the code could be shorter, but you get to see more of what's available this way.

>     import gnu.bytecode.*;

>     public class MetaHelloWorld {
>     	public static void main(String[] args) throws Exception {
>     		// "public class HelloWorld extends java.lang.Object".
>     		ClassType c = new ClassType("HelloWorld");
>     		c.setSuper("java.lang.Object");
>     		c.setModifiers(Access.PUBLIC);

>     		// "public static int add(int, int)".
>     		Method m = c.addMethod("add", "(II)I", Access.PUBLIC | Access.STATIC);
>     		CodeAttr code = m.startCode();
>     		code.pushScope();
>     		code.emitLoad(code.getArg(0));
>     		code.emitLoad(code.getArg(1));
>     		code.emitAdd(Type.intType);
>     		Variable resultVar = code.addLocal(Type.intType, "result");
>     		code.emitDup();
>     		code.emitStore(resultVar);
>     		code.emitReturn();
>     		code.popScope();

>     		// Get a byte[] representing the class file.
>     		// We could write this to disk if we wanted.
>     		byte[] classFile = c.writeToArray();

>     		// Disassemble this class.
>     		// The output is similar to javap(1).
>     		ClassTypeWriter.print(c, System.out, 0);

>     		// Load the generated class into this JVM.
>     		// gnu.bytecode provides ArrayClassLoader, or you can use your own.
>     		ArrayClassLoader cl = new ArrayClassLoader();
>     		cl.addClass("HelloWorld", classFile);

>     		// Actual invocation is just the usual reflection code.
>     		Class<?> helloWorldClass = cl.loadClass("HelloWorld", true);
>     		Class[] argTypes = new Class[] { int.class, int.class };
>     		int result = (Integer) helloWorldClass.getMethod("add", argTypes).invoke(null, 1, 2);
>     		System.err.println(result);
>     	}
>     }

## License

See the file COPYING.

## Author

Per Bothner `<per@bothner.com>`

## How to get it

The `gnu.bytecode` package is currently distributed as part of Kawa, though it can be used independently of the rest of Kawa.

## Bugs and patches

Send them to per@bothner.com, or to the Kawa mailing list.