JRockit JVM Support For AOP, Part 1

Pages: 1, 2, 3, 4

Proposed solution

JVM weaving is the natural answer to most of the issues discussed above. To understand why, we will look at a couple of examples that show the JVM is already doing most of the work necessary to do weaving: When a class gets loaded, the JVM does read the bytecode to build up the data needed to serve the java.lang.reflect.* API purpose. Another example is method dispatching. Modern JVMs compile the bytecode of methods or code blocks to more advanced and efficient constructs and execution flows (doing code inlining where applicable). Due to the HotSwap API requirements, the JRockit JVM (and probably other JVMs too) also does bookkeeping on which method calls which other method, so that a method body can still be hotswapped in all expected places—inlined or not—if its defining class is redefined at runtime.

As a consequence, instead of changing the bytecode to weave in an advice invocation— say before a specific method call—the JVM could actually have knowledge about it and simply do a dispatch to the advice at any matching join point prior to dispatching to the actual method.

As bytecode would be untouched, immediate advantages can be expected, such as:

  • No startup cost due to bytecode instrumentation
  • Full runtime support to add and remove advices at any place, any time, at linear cost
  • Implicit support to advise reflective invocations
  • No extra memory consumption to replicate the class model to some framework specific structures

A detailed description of the proposed JRockit JVM support for AOP will be presented in the second article of this series.

The following code sample serves as the concluding illustration. It dispatches to the static method advice() just before the sayHello() method gets called :

public class Hello {

  // -- the sample method to intercept
  public void sayHello() {
    System.out.println("Hello World");
  }

  // -- using the JRockit JVM support for AOP
  static void weave() throws Throwable {
    // match on method name
    StringFilter methodName = new StringFilter(
        "sayHello",
        StringFilter.Type.EXACT
    );

    // match on callee type
    ClassFilter klass = new ClassFilter(
        Hello.class,
        false,
        null
    );

    // advice is a regular method dispatch
    Method advice = Aspect.class.getDeclaredMethod(
        "advice",
        new Class[0]
    );

    // get a JRockit weaver and subscribe the
    // advice to the join point picked out by the filter
    Weaver w = WeaverFactory.createWeaver();

    w.addSubscription(new MethodSubscription(
        new MethodFilter(
            0,
            null,
            klass,
            methodName,
            null,
            null
        ),
        MethodSubscription.InsertionType.BEFORE,
        advice
    ));
  }

  // -- sample code

  static void test() {
    new Hello().sayHello();
  }

  public static void main(String a[])
  throws Throwable {
    weave();
    test();
  }

  // -- the sample aspect

  public static class Aspect {

    public static void advice() {
        System.out.println("About to say:");
    }
  }
}

Conclusion

Bytecode instrumentation has gained popularity in the Java community to implement advanced technologies such as AOP or transparent services addition in the middleware space. However, it suffers from several key limitations, and its widespread use will cause further issues affecting both scalability and usability.

Since bytecode instrumentation has more or less become the standard way of implementing weaving in AOP, it will suffer, if it hasn't already, from the limitations and problems outlined in this article.

We believe that JVM support for AOP is the natural solution to those problems. We are proposing a subscription-based API that we have implemented in the JRockit JVM, which is closely integrated with the JVM method dispatch internals. The next article in this series will illustrate in more detail the API, and explain how each problem is solved.

Additional Reading

  • AspectWerkz - plain Java AOP framework
  • AspectJ - the de-facto standard for AOP in Java
  • AOSD - Aspect-Oriented Software Development

Jonas Bonér is a senior software engineer at the JRockit team at BEA Systems and is currently working on dynamic AOP, VM weaving and AOP evangelism. He is the founder of the AspectWerkz AOP framework and committer to the AspectJ 5 project.

Joakim Dahlstedt is the CTO of the Java Runtime Products Group at BEA Systems, Inc., where he is responsible for the future development directions for the JVM.

Alexandre Vasseur works as a software engineer at BEA Systems within the Java Runtime Product Group, focusing on Aspect Oriented Technology. He is the co-founder of the AspectWerkz AOP framework and committer on Eclipse AspectJ 5.