Wednesday, August 08, 2007

Possible JIT for Groovy with JVMTI

Nothing involves Groovy bytecode analysis at the moment, but I show you here the possible way to re-define a Java class with a Java 6 JVMTI agent. Yes, I say Java 6 as Java 5 does not support class re-definition through java.lang.instrument package.

As you might know, several AOP systems, that enable load-time weaving, use class transformation at load-time to weave aspects to the existing programs. They use a java JVMTI agent to achieve this.

Now in Java 6, you can do a bit more further as it offers method

Instrumentation.redefineClasses(ClassDefinition[] defs);




I'm experimenting this technique with a normal class, here:

package org.groovy.git.test;

public class TestClass {

public void myMethod(){
System.out.println("a");
}
}



The re-definition process is performed just to change a TestClass object from printing "a" to printing "b".


package org.groovy.git.test;

import java.lang.instrument.ClassDefinition;
import java.lang.instrument.Instrumentation;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

import org.groovy.git.Agent;

public class AgentTest {

public static void main(String[] args) throws Exception {
// get an instrumentation from the agent
Instrumentation i = Agent.getInstrumentation();

// here, print "a"
TestClass t1 = new TestClass();
t1.myMethod();

// doing bytecode manipulation,
// replace a new method body for "myMethod"

CtClass ct = ClassPool.getDefault().get(TestClass.class.getName());
CtMethod m = ct.getDeclaredMethod("myMethod");
m.setBody("{ System.out.println(\"b\");}"); // make it printing "b"
byte[] bytes = ct.toBytecode();

// prepare a new class definition
ClassDefinition[] def=new ClassDefinition[1];
def[0] = new ClassDefinition(TestClass.class, bytes);
i.redefineClasses(def);

// this shows "b"
TestClass t2 = new TestClass();
t2.myMethod();
}

}



You might see that the above code get instrumentation from the Agent class, which is in a jar loaded by -javaagent:jarfile. In this experiment, I use Javassist for bytecode manipulation.

As you expected, the above code will show:

a
b


as the TestClass has been re-defined and its method, myMethod, body's been replaced.

Monday, July 16, 2007

Groovy AOP coming soon on the desktop near you.

I've just committed the early Groovy AOP's grammar, its compilation unit, and ant task. Actually, everything is getting to work now, but I'd like to add some advice caching mechanism to have, at least, some performance impression.

I'm trying to have it released by the end of this month (July 2007).

If you'd like to see what's going on in the mean time, check out its SVN.

Saturday, May 05, 2007

XFire plugin for Grails 0.5 released

I've released the XFire plugin for Grails 0.5 recently. Now it's using XFire 1.2.6 and
Its forked aegis engine has been updated as well. In Grails 0.5, the Artefact APIs for plugin development has been introduced. All Grails core artefacts (domain, controller, etc.) are moved to use these APIs.

This week seems to be a 0.5-plugin-release week. Beside my XFire, we now have Tsuyoshi's Acegi, Sigi's converters, and Peter's remoting plugins running for 0.5. Check them out on Grails Plugins Page.

Tuesday, May 01, 2007

JIT dynamic weaving for Groovy AOP

From the previous post, I was talking about selecting metaclass using pattern will give some benefits for AOP in Groovy. Now I come up with a cool idea of what is that benefit. The point here is about MOP infrastructure of Groovy is flexible enough by letting us to change the metaclass of any class at runtime, and this allow JIT (Just-in-Time) dynamic weaving of aspects for Groovy.

What does it mean by JIT dynamic weaving?

In my current implementation of Groovy AOP, there's a big overhead of matching pointcuts and invoking advices in the AOP metaclass, but this process can be improved by assigning a new, optimised, metaclass to the woven class. This new metaclass will be generated at runtime (using any bytecode manipulation framework) and it will contain a minimum set of instructions for invoking advices (no more matching process). However, there're still some important open questions like conflictions, etc. that need to be further investigated.

I'm pretty sure that this technique can improve some performance for Groovy AOP. Although, it's obviously slower than AspectJ, but it's worth comparing.