Your cup of Byte-Code-Re-Engineering, BCEL style

Your cup of Byte-Code-Re-Engineering, BCEL style

In case you are wondering what this means? To put it simply, its a way to modify a class at runtime using the Jakarta’s BCEL. When I say modify, I mean altering the behaviour of the class by inserting instructions dynamically. The modus operandi is very simple:

  • Load the class with BCEL
  • Modify it
  • Save it so that the original .class file is over-written with the modified one
  • Use the modified class

As annotations start getting popular and the scene is cleared for Aspect Oriented Programming and the likes, byte code re-engineering assumes significance.

But it can be very cumbersome and a bit dangerous as it might lead to very unpredictable results. Nonetheless, it is a very powerful and handy tool.

I will try to brush on how to use the BCEL to achieve our end. I, myself am a novice.

You may start at their official manual, but the examples there doesnt help much. Also, you you go through the extensive Javadocs that can be had by downloading the binaries.

The first thing to do is to definitely use the immensely handy utility BCELifier which translates Java-code we understand to the somewhat difficult to follow BCEL grammar(which is closer to the JVM’s instruction set). Write a small class with a couple of methods and a few simple printlns, etc and do a:

This class will print back the instructions in order to create the TestClass from scratch.

While working with BCEL, you will have to get used to the fact that most of these classes do not work directly with our own dear java.lang.Class. Instead you have to get a org.apache.bcel.classfile.JavaClass in order to bring home the bacon. But you will be thankful for that in a while. Confused? I will tell you the reason: when you want to modify .class files dynamically, the last thing you would want is to mess-around with Java’s default class-loaders. Once a class is loaded in the JVM’s memory, it is very cumbersome to dislodge it and load it afresh. So, the trick is not to load the class in the JVM until you have BCEL-ed it and saved it. And the only way to prevent it is to refrain from temptation of doing a new TestClass() or a TestClass.class or the like.

Here is how to get an instance of JavaClass:

Before we go into specifics, a small gyan:

  • To create a class file from scratch or to modify an existing one, you use ClassGen
  • To create/modify a method, you use MethodGen
  • To create a JVM instruction, you use InstructionFactory

InstructionFactory comes with many constructors, but this one is most handy:

new InstructionFactory(classGen, constantPoolGen);

In case you are wondering what is constantPoolGen, it represents the class file’s ConstantPool area. Refer to JVM Specs for details.
You can get a constantPoolGen thus:

ConstantPoolGen constantPoolGen = new ConstantPoolGen(clazz.getConstantPool());

That done, you would want to modify it. Refer to DestructiveDecorator. You can find the source code here.

Here are some excerpts:

This is how you would modify methods:

Now you are ready to save the modified class file:

The dirtiest work is done in DestructiveDecorator.morphMethod() where I am adding a sysout and then throwing a RuntimeException. Perusal of BCELifier would ease your mind and the mists will lift clear.

I am sure, if you had the guts to stick on this far, you have ceratinly gained something. Atleast you sure could introduce a few nasty sangs in a perfectly working piece of Java code.

Here goes the rest of the gang, RuntimeDecorator:

And the leader of the gang, the DynamicClassDecorator:

And finally the test-code:

I can promise you that the results would be disastrous!
Happy JVM crash.

BTW, now you should be guessing what the blokes do when the write an EJB Container, JSP container or Aspect Oriented Programming for that matter… the stuff they do at the background stands exposed.

Leave a Reply

Your email address will not be published. Required fields are marked *