[index]
[prev] [next]

2. Jiapi Framework

This chapter describes Jiapi's instrumentation framework. It utilizes Jiapi reflection API which was introduced in a previous chapter. The aim is to provide a framework where bytecode manipulations can be logically grouped and reused.

2.1 Introduction

The instrumentation process consists of three tasks: configuration, instrumentation and launching.

Configuration

Configuration specifies the classes and methods for which instrumentation will be done. It also specifies the characteristics of instrumentations.

Instrumentation

Instrumentation is a process of transforming the original Java class into a modified class. The modifications must be done before actual class loading since after a class has been loaded into a Java virtual machine it is not possible to change it anymore (well actually it is possible if the ClassLoader which loaded the class is garbage collected, but that's another story...). Jiapi provides a class alt.jiapi.Loader which can be used to form an in-memory representation for a class (alt.jiapi.reflect.JiapiClass). It is important to understand that in this phase the class is not really loaded into a virtual machine. It is just an object representation of Java bytecode.

After alt.jiapi.Loader has formed an instance of alt.jiapi.reflect.JiapiClass from Java bytecode, it triggers the instrumentation process according to its configuration.

Roles and responsibilities:

Launching

Often the classes are loaded into a virtual machine after they have been modified. alt.jiapi.InstrumentingClassLoader is an example Java class loader which can be used to load classes into a virtual machine after they have been modified by Jiapi instrumentors. The modified classes can also be saved to filesystem and run later with any virtual machine.

2.2 InstrumentorChain and Instrumentors

A configurable chain of Instrumentors form a backbone of the framework. The chain is implemented as a filter design pattern where each Instrumentor acts as a filter for an InstructionList stream.

The most important method which they implement is:

    public interface Instrumentor {
        /**
         * Instrument given InstructionList. 
         * 
         * @param il An InstructionList to instrument
         */
         public void instrument(InstructionList il);
        
        ...
        ...
    }
On instrument method each Instrumentor may manipulate the given InstructionList. The control is then dispatched to the next Instrumentor using forward method. An example of a simple Instrumentor is ClearInstrumentor which clears the instructions from a given InstructionList:
    public class ClearInstrumentor extends AbstractInstrumentor {
        public ClearInstrumentor() {
        }

        public void instrument(InstructionList il) {
            il.clear();
            forward(il);
        }
    }
Jiapi provides a set of predefined Instrumentors. These can be found from a package alt.jiapi.instrumentor. Here's a brief description of each:

The instrumentors are chained together to do something useful. A good analogy for this chaining is Unix shell pipeline where small utility programs are piped together.

[prev] [next]