OpenJava Tutorial


2. Hello World

A MOP version of "hello world" is verbose objects, which print a message for every method call. We choose them as our first example.

The MOP programming in OpenJava is done through three steps :

and We implement the verbose objects through these steps.

2.1. What the base-level program should look like

Most of example programs given in the text are ready to be executed by the OpenJava system and are similar in form to:


public class Hello instantiates VerboseClass {
    public static void main( String[] args ) {
        hello();
    }
    static void hello() {
        System.out.println( "Hello, world." );
    }
}

This is an ordinary source code except for the first line. The annotation in the first line :


instantiates VerboseClass
is a special annotation for OpenJava, and means that the semantics of the class Hello, called metaobject, is specified to be extended by the class VerboseClass, called metaclass. In practice, the source code of the class Hello is translated by the object of the metaclass VerboseClass.

2.2. What the base-level program should be translated

In this example, consider the metaclass VerboseClass to extend the metaobjects to show messages for every call for its methods. In practice, the statement in order to put the message into system standard output is to be inserted at the first line of each methods' body in the class Hello via the metaclass VerboseClass. Then the first source code of class Hello should be translated into:


public class Hello {
    public static void main( String[] args ) {
        System.out.println( "main is called." );
        hello();
    }
    static void hello() {
        System.out.println( "hello is called." );
        System.out.println( "Hello, world." );
    }
}

2.3. Write a meta-level program

Now, we write a meta-level program. What we should do is to translate only method member in the class Hello in the way shown above. We can easily do that if we use the MOP.

In OpenJava, classes are objects as in Smalltalk. We call them class metaobjects when we refer to their meta-level representation. A unique feature of OpenJava is that a class metaobject translates the source code defining the class at compile time. For example, the class metaobject for Hello translates a method declaration hello().

By default, class metaobjects are identity functions; they do not change the program. So, to implement our translation, we define a new metaclass - a new class for class metaobjects - and use it to make the class metaobject for Hello. Such a metaclass VerboseClass has been compiled and is similar to in form to:


import openjava.mop.*;
import openjava.ptree.*;
public class VerboseClass instantiates Metaclass extends OJClass
{
    public void translateDefinition() throws MOPException {
        OJMethod[] methods = getDeclaredMethods();
        for (int i = 0; i < methods.length; ++i) {
            Statement printer = makeStatement(
                "System.out.println( \"" + methods[i] +
                " is called.\" );"
            );
            methods[i].getBody().insertElementAt( printer, 0 );
        }
    }
}   

Here, the metaclass VerboseClass is a base-level class of OpenJava from the view point of meta programming and in fact it declares its metaclass as openjava.mop.Metaclass though could be written in the regular Java. It inherits from openjava.mop.OJClass and overrides one member function.

In order to translate the definition part (callee-side) of the base class Hello, we should override the method translateMethodDeclaration(), which is to be invoked by the system automatically. In the method translateMethodDeclaration(), we can obtain all the method objects which are declared in the base-level class by invoking the method getDeclaredMethods() on the class object this. The method makeStatement() is the partial parser which produces a openjava.ptree.Statement object from a java.lang.String object. Here we produces a statement which print that the method is called, then inserts it at the body for each method.

2.4. Compile, debug, and run

On a Sun workstation, the first class, stored in the file Hello.oj, can be translated into Java source code file named Hello.java and the generated source code can be compiled into byte code file named Hello.class by giving the commands:

% ojc VerboseClass.oj
% ojc Hello.oj

Execution of its bytecode on JVM (Java Virtual Machine) produces the output :


void Hello.main(String[]) is called.
void Hello.hello() is called.
Hello, world.

Please send any message to :
mich@acm.org

Copyright (C) 1999 by Michaki Tatsubori.
Java(TM) is a trademark of Sun Microsystems, Inc.