I'm playing around Soot framework and get some optimised bytecodes after applying its default optimisation to Groovy-generated classes.
This does not help much for speed improvement, but I think it could help reduce the usage of PermGen space.
I've tested with a trivial class, and its file size after optimisation is 8.5% shrinker than the original. I'm expecting that this figure would be large if we optimise a whole application.
Tuesday, August 21, 2007
Optimising Groovy bytecodes with Soot
Posted by chanwit at 6:51 PM 0 comments
Labels: bytecode, Groovy, Java, Optimisation
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.
Posted by chanwit at 6:38 PM 2 comments