This chapter explains the Jiapi events. The event API is designed to get runtime events from an instrumented class. As an API, it is similar to core Java event model. From Jiapi framework's point of view the event API is just an application implemented on top of it. As such, it is a useful example and useful for those applications which need some basic information from a running application.
To utilize the events, application developer implements a listener interface and registers it to an event producer. Current implementation provides a notification mechanism for method events and field access events:
An application component which is interested about method related events can implement a alt.jiapi.event.MethodListener interface. The interface provides callback methods to get notification when a method is entered or when a method exits:
public interface MethodListener extends JiapiListener { public void methodEntered(MethodEvent event); public void methodExited(MethodEvent event); }
Field access events are notified for classes which implement a alt.jiapi.event.FieldListener interface.
public interface FieldListener extends JiapiListener { public void fieldChanging(FieldEvent fe); public void fieldSet(FieldEvent fe); public void fieldGet(FieldEvent fe); }
This example implements MethodListener interface, registers itself to a MethodEventProducer and launches a test class which is instrumented to fire method events.
1 package samples.example1; 2 3 import alt.jiapi.InstrumentationContext; 4 import alt.jiapi.InstrumentationDescriptor; 5 import alt.jiapi.event.MethodEvent; 6 import alt.jiapi.event.MethodEventProducer; 7 import alt.jiapi.event.MethodListener; 8 import alt.jiapi.util.Launcher; 9 10 public class Example1 implements MethodListener { 11 public static void main(String args[]) throws Exception { 12 new Example1(); 13 } 14 15 public Example1() throws Exception { 16 // Configure: 17 InstrumentationContext ctx = new InstrumentationContext(); 18 InstrumentationDescriptor id = new InstrumentationDescriptor(); 19 id.addInclusionRule("test.*"); 20 ctx.addInstrumentationDescriptor(id); 21 22 // Use event API: 23 MethodEventProducer eventProducer = new MethodEventProducer(id); 24 eventProducer.addMethodListener(this); 25 26 // Launch: 27 Launcher launcher = new Launcher("test.Foo", null, ctx); 28 launcher.launch(); 29 } 30 31 public void methodEntered(MethodEvent event) { 32 System.out.println("Method " + event.getClassName() + "." + 33 event.getMethodName() + " entered."); 34 } 35 36 public void methodExited(MethodEvent event) { 37 System.out.println("Method " + event.getClassName() + "." + 38 event.getMethodName() + " exited."); 39 } 40 }
The example is a MethodListener, it implements the required callback methods methodEntered and methodExited. In constructor the example configures itself, registers itself to a MethodEventProducer and launches Jiapi in a just-in-time bytecode weaving mode.
Lines 17-20 configures the context for the instrumentation. The context is configured so that all the classes whose fully qualified name matches test.* will be included in instrumentation.
In lines 23 and 24 a MethodEventProducer is created and a listener is registered.
Lines 27 and 28 are used to launch a class test.Foo with a given InstrumentationContext. alt.jiapi.util.Launcher is a utility which loads the given class with alt.jiapi.InstrumentingClassLoader and calls loaded class' main method. InstrumentingClassLoader first forms an in-memory representation for the class, triggers the instrumentation process for it and then loads the modified class into a Java virtual machine.
To run the example1 put jiapi.jar and all the required third-party libraries (these are listed in README) to your CLASSPATH and issue:
java samples.example1.Example1
You should see console prints when a methods are entered and exited.
Source code for the example can be found from src/samples/example1/.