TransJVM

How to use TransJVM

This document gives an overview of how to use TransJVM. For a more detailed view of the individual components see the API reference.

Installing

Simply include the transjvm.jar file in your class path.
  1. Extract the download to the a directory of your choice eg. JAVA_STUFF/transjvm
    All the TransJVM class files will now be in JAVA_STUFF/transjvm/transjvm.jar
  2. To compile your code, simply include in the classpath
    javac -classpath JAVA_STUFF/transjvm/transjvm.jar MY_JAVA_SOURCE

Logical structure of TransJVM

The root of the TransJVM structure is the class net.sf.transjvm.TClass.
Note that the structural hierarchy has nothing to do with the inheritance hierarchy, but is similar to a GUI hierachy with a Window at the root and various components forming a tree below.

The structure

TClass

The TClass class is the root of the TransJVM structure. It is analogous to the class java.lang.Class, except that TClass is used to construct the bytes of a ".class" files from a logical structure, whereas java.lang.Class builds a logical structure from the bytes of a ".class" file.
It is is the parent to TMethod, TConstructor and TField.
To create a new java class and get the byte array:
  1. Create a new TClass with TClass cls = new TClass(name, flags)
  2. Add constructors, methods and fields with cls.add(member)
  3. Get the bytes with byte[] bytes = cls.getBytes()

TMethod

The TMethod class consists of a Frame and code in the form of a Statement.
So, to create the method:
public String hello() {
    return "Hello";
}
Use the following code:
Frame f = new Frame(new TypeID[0], false);
Statement code = Statement._return(Expression.constant("Hello"));
TMethod method = new TMethod("hello", Flags.PUBLIC, frame, TypeID.STRING, code);

TConstructor

TConstructor is very similar to TMethod, except it does not have a name or a return type. Note that all constructors must call a superclass constructor or another constructor of the same class within their code.

TField

TField represents fields in a class. Suppose the java source code for class XXX includes the code
static int count;
The same is accomplished in TransJVM with:
TClass cls = new TClass("XXX", Flags.PUBLIC);
TField field = new TField("count", Flags.STATIC, TypeID.INT);
cls.add(field);

Frame

A frame represents the parameters of a method and it local variables. It corresponds to the stack frame during the execution of its owning method.

There is a one to one relation between a frame and a method. Each method must contain exactly one Frame. Each Frame must belong to exactly one method.

A Frame is created by specifying its parameters and whether it is static. For example the Frame for the java.lang.String method

indexOf(String str, int fromIndex)
would be
TypeID[] parameters = new TypeID[] { TypeID.STRING, TypeID.INT };
Frame frameForIndexOf = new Frame(parameters, false);
Note that we do not care what the method is called or its return type.

Once we have a frame we can get locals variables with

Variable localVariable = frame.variable(type);
Variables can be returned for reuse with:
frame.free(localVariable);
Frame also allows for local variables to have a name and type attached for debugging purposes. To attach a name to a variable for the duration of Statement s, use: s = frame.name(variable, name, s);

Statements

Statements are the most important part of TransJVM. They are the executable part of a method or constructor. There are about a dozen basic statements provided in TransJVM, but any complex statement can be created out of these building blocks.

Combining statements

You may have noted that TMethod and TConstructor accept only a single statement, but most methods and constructors consist of many statements. Several statements can be combined into one statement that executes those statements in turn.

A pair of statements s1 and s2 can be combined into one statement with Statement pair = s1.concat(s2); A list of statements can be combined into one with Statement list = Statement.list(mylist), where myList is a List of Statements

Flow control

Unconditional branches

Use Statement._goto(label) Eg.
Label label = new Label();
Statement go = Statement._goto(label);
Statement ignore = Statement.RETURN_VOID;
Statement jumpOver = go.concat(ignore).concat(label);

Conditional branches

For simple if-then branches use Statement._if(cond, stmt) Otherwise see Conditional Branching

Throwing an exception

To throw an exception use Statement._throw(exception)

Guarding against exceptions

There are two methods avaiable for this:
Statement.guarded(body, errorValue, handlers)
and Statement.always(body, postscript)

Returning values

To end execution of a method and return a value use Statement._return(value);
or Statement.RETURN_VOID;
Note that value must have the same type as the method.

Assignment

See Variables

Annotation

Line numbers

To attach a line number to a statment use: stm = Statement.line(stm, line);

Expressions

Expressions are the smallest building blocks of TransJVM, Expressions include literals such as numbers and strings, method calls, operator expressions( eg. a + b) and variables. An expression represents the code require to produce some value at run time. Here are three expressions in Java:
  1. 1
  2. new StringBuffer("<html>")
  3. (7 + x) / y > 2
Here are the same expressions in TransJVM:
  1. Expression.constant(1)
  2. ConstructorID newBuffer = new ConstructorID(TypeID.forName("java.lang.StringBuffer"), TypeID.STRING);
    newBuffer.newInstance(Expression.constant("<html>"))
  3. Expression.constant(7).math(Operator.ADD, x).math(Operator.DIV, y).compare(Operator.GT, Expression.constant(2))

Constants

To create a non-boolean constant value use Expression.constant(value). For booleans use Expression.TRUE or Expression.FALSE.

Mathematic expressions

Use expression1.math(operator, expression2) For example x + y is x.math(Operator.ADD, y)

Comparison expressions

Use expression1.compare(operator, expression2) For example x >= y is x.compare(Operator.GE, y)

Bitwise and logical expressions

For direct evaluation use expression1.bitwise(operator, expression2). For example x & y is x.bitwise(Operator.AND, y).

For shortcut or lazy evaluation (ie. only evaluate y in x && y if x is true) use expression1.shortCut(operator, expression2). For example x && y is x.shortCut(Operator.AND, y).

Method Calls

To call a method use MethodID.call(arg0, arg1...). For example "Hello".substring(2) is substring.call(Expression.constant("Hello"), Expression.constant(2)) where substring = MethodID.virtual(TypeID.STRING, TypeID.STRING, "substring", TypeID.INT)

Conditional branching

To make a conditional branch depending on the value of (boolean) expression use: exp.branch(branchOnTrue, target) For example, to get a Statement that jumps to 'end' when cond is false Statement toEnd = cond.branch(false, end);

Variables

Variables can hold values, so extend Expressions with method to store values. When variables are being read, just treat them as Expressions. There are two ways of writing to a variable:
  1. As a statement: var.store(exp) This returns a statement which stores exp in var.
  2. As an expression: var.assign(exp) This returns an expression which has the same value as exp, but as a side effect stores exp in var.

Naming variables

See Frame