# Package org.biojava.utils.bytecode

package org.biojava.utils.bytecode
A Java object-model for a Java Bytecode Macro-Assembler.

## Description

The ByteCode package is able to generate Java Bytecode that can be used to define Java classes. It is not restricted to things that can be expressed as Java code (as in .java files), and is more flexible than basic Java bytecode.

This package supports generating classes, interfaces, methods, fields, and the like. It follows the macro-assembler pattern, where users can effectively extend the bytecode instruction set with their own instructions that at compile time expand to real bytecode instructions. Many useful pseudo-instructions are provided, such as IfExpression. This package also supports some advanced functionality such as templating. Templating supports both object and primitive types and types can be resolved at the level of complete methods or single expressions.

The ByteCode package has no support whatsoever for editing Java Bytecode. In particular, there is no support for search-and-replace or optimization.

The main classes for generating bytecode are `CodeUtils`, `ByteCode`, `InstructionVector` and `GeneratedCodeClass`. You will probably also use `GeneratedClassLoader`, as it does the actual work of building and loading classes.

It is probably a requirement of using this package effectively that you have memorised or have handy a copy of the Java VM specification. This is available from the Sun web site.

## Class Reflection

The ByteCode package represents classes, methods and fields using its own APIs. These, for obvious reasons, closely resemble those provided by the core Java APIs. The three interfaces `CodeClass`, `CodeMethod` and `CodeField` represent these basic concepts.

Classes from the Java VM are reflected into this model using `IntrospectedCodeClass`. To get an instance, use the factory method `IntrospectedCodeClass.forClass(Class)` or `IntrospectedCodeClass.forClass(String)`.

## Class Generation

Classes that you generate yourself will be represented by instances of `GeneratedCodeClass`. Methods are created by calling `GeneratedCodeClass.createMethod(java.lang.String, org.biojava.utils.bytecode.CodeClass, org.biojava.utils.bytecode.CodeClass[], java.lang.String[], int)`, which will return a `GeneratedCodeMethod`. The method can then be implemented by associating a `CodeGenerator` with the method on that particular class using `GeneratedCodeClass.setCodeGenerator(org.biojava.utils.bytecode.CodeMethod, org.biojava.utils.bytecode.CodeGenerator)`.

Fields are generated by calling `GeneratedCodeClass.createField(java.lang.String, org.biojava.utils.bytecode.CodeClass, int)`.

The classes themselves are instantiated into the VM using `GeneratedClassLoader`. This implements `ClassLoader.defineClass(byte[], int, int)` and over-rides the other necessary book-keeping methods. You may wish to sub-class or wrap this class in an application to generate the desired behavior.

## An example

We are going to implement HelloWorld in bytecode. Here is the (annotated) code.

Firstly, lets define our application structure... ``

    public class BCHelloWorld {
      public static void main(String[] args)
      throws Throwable {
        createHelloWorld().run();
      }

      public static Runnable createHelloWorld() {
        ...
      }
    }

We will fill in the createHelloWorld method to actualy do the work of printing out hello world by implementing a Runnable with a run() method. Firstly, we need a load of types, methods and a field or two. `

    CodeClass cl_Object = IntrospectedCodeClass.forClass(Object.class);
    CodeClass cl_String = IntrospectedCodeClass.forClass(String.class);
    CodeClass cl_System = IntrospectedCodeClass.forClass(System.class);
    CodeClass cl_PrintStream = IntrospectedCodeClass.forClass(PrintStream.class);
    CodeClass cl_Void = IntrospectedCodeClass.forClass(Void.TYPE);
    CodeClass cl_Runnable = IntrospectedCodeClass.forClass(Runnable.class);

    CodeField f_System_out = cl_System.getFieldByName("out");

    CodeMethod m_PrintStream_printLn = cl_PrintStream.getMethod(
        "printLn",
        new CodeClass[] { cl_String } );
    CodeMethod m_Object_init = cl_Object.getConstructor(CodeUtils.EMPTY_LIST);

` Now we are ready to create our code class. It will be called HelloWorldRunnable, inherit directly from Object, implement Runnable, and be a public class. `

    GeneratedCodeClass ourClass = new GeneratedCodeClass(
        "HelloWorldRunnable",
        cl_Object,
        new CodeClass[] { cl_Runnable },
        CodeUtils.ACC_PUBLIC | CodeUtils.ACC_SUPER);

` This will need a constructor. Remember, constructors have the name >initinvalid input: '&lt':, and you must be sure to call the super-constructor explicitly. Normaly the javac compiler does this for you. `

    GeneratedCodeMethod init = ourClass.createMethod(
        "<init>",
        cl_Void,
        CodeUtils.EMPTY_LIST,
        CodeUtils.ACC_PUBLIC);
    InstructionVector initIV = new InstructionVector();
    initIV.add(ByteCode.make_aload(init.getThis()));
    initIV.add(ByteCode.make_invokespecial(m_Object_init));
    initIV.add(ByteCode.make_return());
    ourClass.setCodeGenerator(init, initIV);

` To be a Runnable implementation, we must also provide a run() method. This will take no arguments, return void and be publically accessible. Also, the body of this method will print out "Hello World" and then we can all feel pleased with ourselves. `

    GeneratedCodeMethod run = ourClass.createMethod(
        "run",
        cl_Void,
        CodeUtils.EMPTY_LIST,
        CodeUtils.ACC_PUBLIC);
    InstructionVector runIV = new InstructionVector();
    runIV.add(ByteCode.make_getstatic(f_System_out));
    runIV.add(ByteCode.make_sconst("Hello World");
    runIV.add(ByteCode.make_invokevirtual(m_PrintStream_printLn));
    runIV.add(ByteCode.make_return());
    ourClass.setCodeGenerator(run, runIV);

` Now we want to load in a class with this deffinition and instantiate it. `

    GeneratedClassLoader gcl = new GeneratedClassLoader(class.getClassLoader());
    Class newClass = gcl.defineClass(ourClass);
    return (Runnable) newClass.newInstance();

` And there you are. With any luck, if you type all of this in, and the fates smile on you, and biojava.jar is arround for linking against, you should have generated your very own unuque HelloWorld class.

Good luck.

Class
Description
ByteCode
Factory for objects which encapsulate individual Java bytecode instructions.
CodeClass
Interface for Java classes within the bytecode generation framework.
CodeContext
Interface which encapsulates the stream to which Java bytecode can be written.
CodeException
An exception indicating that something went wrong generating byte code.
CodeField
Wrap up details about a field in a Java class file.
CodeGenerator
Interface for an object which can produce Java bytecode.
CodeMethod
Wrap up details about a method in a Java class file
CodeUtils
Utility code for things you will frequently need.
ConstantPool
Build a Java class file constant pool.
GeneratedClassLoader
A class loader that actually produces real Java classes from GeneratedCodeClass instances.
GeneratedCodeClass
A CodeClass implementation that is used to generate new classes.
GeneratedCodeMethod
A method that will be generated.
IfExpression
A CodeGenerator that provides something semanticaly identical to if.
Instruction
Base class for java bytecode instructions.
InstructionVector
A list of Instructions and/or other CodeGenerator objects.
IntrospectedCodeClass
CodeClass instances that represent normal Java Class objects.
Label
A Label used to mark a position in byte code.
LocalVariable
A local variable.
MarkLabel
A CodeGenerator that just marks a label that can be used for jumps.
ParametricCodeGenerator
ParametricType
A template type.
PParametricCodeGenerator