JBoss.org Community Documentation

Chapter 6. Instrumentation

6.1. Load-time instrumentation
6.2. Compile-time instrumentation
6.3. Understanding the provided AOP descriptor

In order to store an object in POJO Cache, it must be either instrumented or made serializable. Instrumentation is the most optimal approach since it preserves object identity and provides field granular replication. POJO Cache currently uses the JBoss AOP project to provide instrumentation, so the same processes described in the AOP documentation are used with POJO Cache.

The primary input to JBoss AOP is the AOP binding file, which is responsible for specifying which classes should be instrumented. POJO Cache provides a binding file, pojocache-aop.xml , which matches all classes that have been annotated with the @Replicable annotation. Advanced users may choose to alter this definition to instrument classes in other various interesting ways. However, it is recommended to just stick with the default annotation binding.

The instrumentation process can be executed at either load-time, or compile-time. Load-time instrumentation uses a Java agent to intercept and modify classes as they are loaded; whereas compile-time instrumentation requires running aopc as part of the compilation process.

Note

Load-time is the recommended approach, since compile-time instrumentation adds hard dependencies to the weaved bytecode which ties the output to a particular version of JBoss AOP.

Load-time instrumentation uses a Java agent to intercept all classes loaded by the JVM. As they are loaded JBoss AOP instruments them, allowing POJO Cache to monitor field changes. To enable load time instrumentation the JVM must be started with the following specified:

  1. The jboss.aop.path system property set to the location of pojocache-aop.xml

  2. A javaagent argument which includes jboss-aop-jdk50.jar

These requirements lead to the following example ant task:


<java classname="Foo" fork="yes">
   <jvmarg value="-javaagent:lib/jboss-aop.jar"/>
   <jvmarg value="-Djboss.aop.path=etc/META-INF/pojocache-aop.xml"/>
   <classpath refid="test.classpath"/>
</java>

There is also a pojo-run command line script in the POJO Cache distribution that passes the proper arguments to the JVM for you.


$ pojo-run -classpath myclasses org.foo.Bar

Once the JVM is executed in this manner, any class with the @Replicable annotation will be instrumented when it is loaded.

While load-time is the preferred approach, it is also possible to instrument classes at compile-time. To do this, the aopc tool is used, with the following requirements:

  1. The aoppath option must point to the location of pojocache-aop.xml

  2. The src option must point to the location of your class files that are to be instrumented. This is typically the output folder of a javac run.

The following is an example ant task which performs compile-time instrumentation:


<taskdef name="aopc" classname="org.jboss.aop.ant.AopC" classpathref="aop.classpath"/>
<target name="aopc" depends="compile" description="Precompile aop class">
    <aopc compilerclasspathref="aop.classpath" verbose="true">
       <src path="${build}"/>
       <include name="org/jboss/cache/aop/test/**/*.class"/>
       <aoppath path="${output}/resources/pojocache-aop.xml"/>
       <classpath path="${build}"/>
       <classpath refid="lib.classpath"/>
    </aopc>
</target>

In this example, once the aopc target is executed the classes in the build directory are modified. They can then be packaged in a jar and loaded using the normal Java mechanisms.

The advanced user might decide to alter the provided AOP descriptor. In order to do this, it is important to understand the reasons behind what is provided, and what is required by POJO Cache. Previous sections have mentioned that any class with the @Replicable annotation will be instrumented. This happens, because the provided AOP descriptor, pojocache-aop.xml , has a prepare statement which matches any class (or subclass) using the annotation. This is shown in the following snippet:


<prepare expr="field(* $instanceof{@org.jboss.cache.pojo.annotation.Replicable}->*)"/>

More specifically, any code which accesses a field on a class which has been annotated with @Replicable , will be instrumented: The "field" pointcut in the expression matches both read and write operations. The wildcard "*" indicates that all java protection modes are intercepted (private, package, protected, public). The $instanceof expression refers to any annotation that subclasses @Replicable . Finally, the ending wildcard allows the matched field to have any name.