Using the ASM Toolkit for Bytecode Manipulation
Pages: 1, 2, 3, 4
Testing
First of all, we need to ensure that transformed class is functioning
properly after transformation, and that the injected code actually works.
These two test cases are represented by the testCounter() and
testNotifier() methods below.
public class NotifierClassVisitorTest
extends TestCase {
private TestListener listener;
private Counter counter;
public void testCounter() {
int n1 = counter.count();
counter.increment();
int n2 = counter.count();
assertEquals( n1+1, n2);
}
public void testNotifier() {
counter.count();
counter.increment();
counter.count();
List events = listener.getEvents();
assertEquals( 3, events.size());
}
...
The testCounter() method is a typical test case
that should ensure that code is functioning as expected.
The testNotifier() tests new functionality
added by the transformer. In both cases, all initialization is done in
the following setUp() method.
public void setUp() throws Exception {
super.setUp();
Class cc = loadClass( TEST_CLASS);
counter = ( Counter) cc.newInstance();
listener = new TestListener();
(( Notifier) counter).addListener( listener);
}
The transformed class is loaded in the loadClass()
method and a new instance is created. The same instance
is cast to the Notifier interface in order
to register TestListener, which records
notifications and enables retrieving them with the getEvents()
method, which is used in testNotifier().
The loadClass() method uses a custom ClassLoader,
which transforms classes on the fly using ASM with NotifierClassVisitor.
private Class loadClass(final String className) throws ClassNotFoundException {
ClassLoader cl = new TestClassLoader( className);
return cl.loadClass( className);
}
The code above assumes that a default constructor exists. The complete source code is available in the Resources section below.
Conclusion
As shown above, ASM allows us to write very compact code for generating new classes
and transforming existing bytecode. Using the described approach and
ASMifierClassVisitor, it is easy to implement quite advanced transformations.
In some cases, it could make sense to use CGLIB
which provides code transformation templates and a more high-level API on top of ASM,
but a lack of documentation and tutorials make it difficult to learn.
Resources
- ASM home page
- "ASM: A code manipulation tool to implement adaptable systems" (PDF)
- Frequently Asked Questions collected by Mark Proctor
- CGLIB project
- Java Virtual Machine Specification and JVM Instruction Set.
- Source code for this article
Eugene Kuleshov is an independent consultant with over 15 years of experience in software design and development.
Return to ONJava.com.
- Trackback from http://neural.ee.ncku.edu.tw/~ccy0927/blog/archives/000187.html
Time to deprecate javac?
2004-10-14 01:28:03 [View]
-
Simpler alternative?
2004-10-07 02:45:34 rexguo [View]